写在前面

接slave接口篇,本文继续打包一个AXI4-Full-Master接口的IP,学习下源码,再仿真看看波形。

带你快速入门AXI4总线--AXI4-Full篇(2)----XILINX AXI4-Full接口IP源码仿真分析(Slave接口)https://blog.csdn.net/wuzhikaidetb/article/details/121594798https://blog.csdn.net/wuzhikaidetb/article/details/121594798带你快速入门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接口,接口类型选择从机master,数据位宽32位,然后点击Next

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

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

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

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

2、Master接口的源码分析

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

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

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

        参数主要是数据、地址、ID的位宽;目标从机的基地址。

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

此外还有功能接口:1、INIT_AXI_TXN:开始发送事务信号;2、TXN_DONE:事务完成信号;3、ERROR:错误信号。

`timescale 1 ns / 1 psmodule myip_axi4_Full_master_v1_0_M00_AXI #(// Users to add parameters here// User parameters ends// Do not modify the parameters beyond this line// Base address of targeted slaveparameter  C_M_TARGET_SLAVE_BASE_ADDR  = 32'h40000000,// Burst Length. Supports 1, 2, 4, 8, 16, 32, 64, 128, 256 burst lengthsparameter integer C_M_AXI_BURST_LEN    = 16,// Thread ID Widthparameter integer C_M_AXI_ID_WIDTH  = 1,// Width of Address Busparameter integer C_M_AXI_ADDR_WIDTH    = 32,// Width of Data Busparameter integer C_M_AXI_DATA_WIDTH  = 32,// Width of User Write Address Busparameter integer C_M_AXI_AWUSER_WIDTH  = 0,// Width of User Read Address Busparameter integer C_M_AXI_ARUSER_WIDTH    = 0,// Width of User Write Data Busparameter integer C_M_AXI_WUSER_WIDTH   = 0,// Width of User Read Data Busparameter integer C_M_AXI_RUSER_WIDTH    = 0,// Width of User Response Busparameter integer C_M_AXI_BUSER_WIDTH = 0)(// Users to add ports here// User ports ends// Do not modify the ports beyond this line// Initiate AXI transactionsinput wire  INIT_AXI_TXN,// Asserts when transaction is completeoutput wire  TXN_DONE,// Asserts when ERROR is detectedoutput reg  ERROR,// Global Clock Signal.input wire  M_AXI_ACLK,// Global Reset Singal. This Signal is Active Lowinput wire  M_AXI_ARESETN,// Master Interface Write Address IDoutput wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_AWID,// Master Interface Write Addressoutput wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,// Burst length. The burst length gives the exact number of transfers in a burstoutput wire [7 : 0] M_AXI_AWLEN,// Burst size. This signal indicates the size of each transfer in the burstoutput wire [2 : 0] M_AXI_AWSIZE,// Burst type. The burst type and the size information, // determine how the address for each transfer within the burst is calculated.output wire [1 : 0] M_AXI_AWBURST,// Lock type. Provides additional information about the// atomic characteristics of the transfer.output wire  M_AXI_AWLOCK,// Memory type. This signal indicates how transactions// are required to progress through a system.output wire [3 : 0] M_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.output wire [2 : 0] M_AXI_AWPROT,// Quality of Service, QoS identifier sent for each write transaction.output wire [3 : 0] M_AXI_AWQOS,// Optional User-defined signal in the write address channel.output wire [C_M_AXI_AWUSER_WIDTH-1 : 0] M_AXI_AWUSER,// Write address valid. This signal indicates that// the channel is signaling valid write address and control information.output wire  M_AXI_AWVALID,// Write address ready. This signal indicates that// the slave is ready to accept an address and associated control signalsinput wire  M_AXI_AWREADY,// Master Interface Write Data.output wire [C_M_AXI_DATA_WIDTH-1 : 0] M_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.output wire [C_M_AXI_DATA_WIDTH/8-1 : 0] M_AXI_WSTRB,// Write last. This signal indicates the last transfer in a write burst.output wire  M_AXI_WLAST,// Optional User-defined signal in the write data channel.output wire [C_M_AXI_WUSER_WIDTH-1 : 0] M_AXI_WUSER,// Write valid. This signal indicates that valid write// data and strobes are availableoutput wire  M_AXI_WVALID,// Write ready. This signal indicates that the slave// can accept the write data.input wire  M_AXI_WREADY,// Master Interface Write Response.input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_BID,// Write response. This signal indicates the status of the write transaction.input wire [1 : 0] M_AXI_BRESP,// Optional User-defined signal in the write response channelinput wire [C_M_AXI_BUSER_WIDTH-1 : 0] M_AXI_BUSER,// Write response valid. This signal indicates that the// channel is signaling a valid write response.input wire  M_AXI_BVALID,// Response ready. This signal indicates that the master// can accept a write response.output wire  M_AXI_BREADY,// Master Interface Read Address.output wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_ARID,// Read address. This signal indicates the initial// address of a read burst transaction.output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR,// Burst length. The burst length gives the exact number of transfers in a burstoutput wire [7 : 0] M_AXI_ARLEN,// Burst size. This signal indicates the size of each transfer in the burstoutput wire [2 : 0] M_AXI_ARSIZE,// Burst type. The burst type and the size information, // determine how the address for each transfer within the burst is calculated.output wire [1 : 0] M_AXI_ARBURST,// Lock type. Provides additional information about the// atomic characteristics of the transfer.output wire  M_AXI_ARLOCK,// Memory type. This signal indicates how transactions// are required to progress through a system.output wire [3 : 0] M_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.output wire [2 : 0] M_AXI_ARPROT,// Quality of Service, QoS identifier sent for each read transactionoutput wire [3 : 0] M_AXI_ARQOS,// Optional User-defined signal in the read address channel.output wire [C_M_AXI_ARUSER_WIDTH-1 : 0] M_AXI_ARUSER,// Write address valid. This signal indicates that// the channel is signaling valid read address and control informationoutput wire  M_AXI_ARVALID,// Read address ready. This signal indicates that// the slave is ready to accept an address and associated control signalsinput wire  M_AXI_ARREADY,// Read ID tag. This signal is the identification tag// for the read data group of signals generated by the slave.input wire [C_M_AXI_ID_WIDTH-1 : 0] M_AXI_RID,// Master Read Datainput wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA,// Read response. This signal indicates the status of the read transferinput wire [1 : 0] M_AXI_RRESP,// Read last. This signal indicates the last transfer in a read burstinput wire  M_AXI_RLAST,// Optional User-defined signal in the read address channel.input wire [C_M_AXI_RUSER_WIDTH-1 : 0] M_AXI_RUSER,// Read valid. This signal indicates that the channel// is signaling the required read data.input wire  M_AXI_RVALID,// Read ready. This signal indicates that the master can// accept the read data and response information.output wire  M_AXI_RREADY);

NO.2----函数、寄存器定义:

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

clogb2这个function实现的功能:以2为底取对数,主要是用来计算位宽。

状态机的状态定义:初始状态、发送状态、接收状态、比较(检查错误)状态。

 // function called clogb2 that returns an integer which has the//value of the ceiling of the log base 2// function called clogb2 that returns an integer which has the // value of the ceiling of the log base 2.                      function integer clogb2 (input integer bit_depth);              begin                                                           for(clogb2=0; bit_depth>0; clogb2=clogb2+1)                   bit_depth = bit_depth >> 1;                                 end                                                           endfunction                                                     // C_TRANSACTIONS_NUM is the width of the index counter for // number of write or read transaction.localparam integer C_TRANSACTIONS_NUM = clogb2(C_M_AXI_BURST_LEN-1);// Burst length for transactions, in C_M_AXI_DATA_WIDTHs.// Non-2^n lengths will eventually cause bursts across 4K address boundaries.localparam integer C_MASTER_LENGTH    = 12;// total number of burst transfers is master length divided by burst length and burst sizelocalparam integer C_NO_BURSTS_REQ = C_MASTER_LENGTH-clogb2((C_M_AXI_BURST_LEN*C_M_AXI_DATA_WIDTH/8)-1);// Example State machine to initialize counter, initialize write transactions, // initialize read transactions and comparison of read data with the // written data words.parameter [1:0] IDLE = 2'b00, // This state initiates AXI4Lite transaction // after the state machine changes state to INIT_WRITE // when there is 0 to 1 transition on INIT_AXI_TXNINIT_WRITE   = 2'b01, // This state initializes write transaction,// once writes are done, the state machine // changes state to INIT_READ INIT_READ = 2'b10, // This state initializes read transaction// once reads are done, the state machine // changes state to INIT_COMPARE INIT_COMPARE = 2'b11; // This state issues the status of comparison // of the written data with the read data reg [1:0] mst_exec_state;// AXI4LITE signals//AXI4 internal temp signalsreg [C_M_AXI_ADDR_WIDTH-1 : 0]  axi_awaddr;reg      axi_awvalid;reg [C_M_AXI_DATA_WIDTH-1 : 0]  axi_wdata;reg   axi_wlast;reg   axi_wvalid;reg      axi_bready;reg [C_M_AXI_ADDR_WIDTH-1 : 0]   axi_araddr;reg      axi_arvalid;reg     axi_rready;//write beat count in a burstreg [C_TRANSACTIONS_NUM : 0]    write_index;//read beat count in a burstreg [C_TRANSACTIONS_NUM : 0]    read_index;//size of C_M_AXI_BURST_LEN length burst in byteswire [C_TRANSACTIONS_NUM+2 : 0]    burst_size_bytes;//The burst counters are used to track the number of burst transfers of C_M_AXI_BURST_LEN burst length needed to transfer 2^C_MASTER_LENGTH bytes of data.reg [C_NO_BURSTS_REQ : 0]    write_burst_counter;reg [C_NO_BURSTS_REQ : 0]   read_burst_counter;reg      start_single_burst_write;reg    start_single_burst_read;reg     writes_done;reg     reads_done;reg      error_reg;reg   compare_done;reg    read_mismatch;reg   burst_write_active;reg      burst_read_active;reg [C_M_AXI_DATA_WIDTH-1 : 0]    expected_rdata;//Interface response error flagswire     write_resp_error;wire   read_resp_error;wire    wnext;wire      rnext;reg   init_txn_ff;reg     init_txn_ff2;reg    init_txn_edge;wire      init_txn_pulse;

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

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

 // I/O Connections assignments//I/O Connections. Write Address (AW)assign M_AXI_AWID    = 'b0;//The AXI address is a concatenation of the target base address + active offset rangeassign M_AXI_AWADDR   = C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;//Burst LENgth is number of transaction beats, minus 1assign M_AXI_AWLEN    = C_M_AXI_BURST_LEN - 1;//Size should be C_M_AXI_DATA_WIDTH, in 2^SIZE bytes, otherwise narrow bursts are usedassign M_AXI_AWSIZE  = clogb2((C_M_AXI_DATA_WIDTH/8)-1);//INCR burst type is usually used, except for keyhole burstsassign M_AXI_AWBURST    = 2'b01;assign M_AXI_AWLOCK   = 1'b0;//Update value to 4'b0011 if coherent accesses to be used via the Zynq ACP port. Not Allocated, Modifiable, not Bufferable. Not Bufferable since this example is meant to test memory, not intermediate cache. assign M_AXI_AWCACHE   = 4'b0010;assign M_AXI_AWPROT = 3'h0;assign M_AXI_AWQOS = 4'h0;assign M_AXI_AWUSER    = 'b1;assign M_AXI_AWVALID    = axi_awvalid;//Write Data(W)assign M_AXI_WDATA    = axi_wdata;//All bursts are complete and aligned in this exampleassign M_AXI_WSTRB    = {(C_M_AXI_DATA_WIDTH/8){1'b1}};assign M_AXI_WLAST   = axi_wlast;assign M_AXI_WUSER = 'b0;assign M_AXI_WVALID = axi_wvalid;//Write Response (B)assign M_AXI_BREADY   = axi_bready;//Read Address (AR)assign M_AXI_ARID  = 'b0;assign M_AXI_ARADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr;//Burst LENgth is number of transaction beats, minus 1assign M_AXI_ARLEN    = C_M_AXI_BURST_LEN - 1;//Size should be C_M_AXI_DATA_WIDTH, in 2^n bytes, otherwise narrow bursts are usedassign M_AXI_ARSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1);//INCR burst type is usually used, except for keyhole burstsassign M_AXI_ARBURST    = 2'b01;assign M_AXI_ARLOCK   = 1'b0;//Update value to 4'b0011 if coherent accesses to be used via the Zynq ACP port. Not Allocated, Modifiable, not Bufferable. Not Bufferable since this example is meant to test memory, not intermediate cache. assign M_AXI_ARCACHE   = 4'b0010;assign M_AXI_ARPROT = 3'h0;assign M_AXI_ARQOS = 4'h0;assign M_AXI_ARUSER    = 'b1;assign M_AXI_ARVALID    = axi_arvalid;//Read and Read Response (R)assign M_AXI_RREADY  = axi_rready;//Example design I/Oassign TXN_DONE   = compare_done;//Burst size in bytesassign burst_size_bytes    = C_M_AXI_BURST_LEN * C_M_AXI_DATA_WIDTH/8;

NO.4----捕获写事务开始信号的上升沿:

        写事务开始信号INIT_AXI_TXN打拍,并捕获其上升沿,作为开始发送的标志信号。

 assign init_txn_pulse   = (!init_txn_ff2) && init_txn_ff;//Generate a pulse to initiate AXI transaction.always @(posedge M_AXI_ACLK)                                            begin                                                                        // Initiates AXI transaction delay    if (M_AXI_ARESETN == 0 )                                                   begin                                                                    init_txn_ff <= 1'b0;                                                   init_txn_ff2 <= 1'b0;                                                   end                                                                               else                                                                       begin  init_txn_ff <= INIT_AXI_TXN;init_txn_ff2 <= init_txn_ff;                                                                 end                                                                      end 

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

        写地址准备信号axi_awvalid:当单次突发写信号start_single_burst_write有效时,将其拉高。

写地址通道握手成功时同时对首地址axi_awaddr赋值。

   always @(posedge M_AXI_ACLK)                                   begin                                                                if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                           begin                                                            axi_awvalid <= 1'b0;                                           end                                                              // If previously not valid , start next transaction                else if (~axi_awvalid && start_single_burst_write)                 begin                                                            axi_awvalid <= 1'b1;                                           end                                                              /* Once asserted, VALIDs cannot be deasserted, so axi_awvalid      must wait until transaction is accepted */                         else if (M_AXI_AWREADY && axi_awvalid)                             begin                                                            axi_awvalid <= 1'b0;                                           end                                                              else                                                               axi_awvalid <= axi_awvalid;                                      end                                                                // Next address after AWREADY indicates previous address acceptance    always @(posedge M_AXI_ACLK)                                         begin                                                                if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                            begin                                                            axi_awaddr <= 'b0;                                             end                                                              else if (M_AXI_AWREADY && axi_awvalid)                             begin                                                            axi_awaddr <= axi_awaddr + burst_size_bytes;                   end                                                              else                                                               axi_awaddr <= axi_awaddr; 

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

        写数据准备信号axi_wvalid:当单次突发写信号start_single_burst_write有效时,将其拉高。

写入最后一个数据时拉高axi_wlast。

每写入一个数据,突发写入长度计数器write_index累加1.

在写入数据期间axi_wdata从0累加1.

   assign wnext = M_AXI_WREADY & axi_wvalid;    //写数据持续期间                                   // WVALID logic, similar to the axi_awvalid always block above                      always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                                        begin                                                                         axi_wvalid <= 1'b0;                                                         end                                                                           // If previously not valid, start next transaction                              else if (~axi_wvalid && start_single_burst_write)                               begin                                                                         axi_wvalid <= 1'b1;                                                         end                                                                           /* If WREADY and too many writes, throttle WVALID                               Once asserted, VALIDs cannot be deasserted, so WVALID                           must wait until burst is complete with WLAST */                                 else if (wnext && axi_wlast)                                                    axi_wvalid <= 1'b0;                                                           else                                                                            axi_wvalid <= axi_wvalid;                                                     end                                                                               //WLAST generation on the MSB of a counter underflow                                // WVALID logic, similar to the axi_awvalid always block above                      always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                                        begin                                                                         axi_wlast <= 1'b0;                                                          end                                                                           // axi_wlast is asserted when the write index                                   // count reaches the penultimate count to synchronize                           // with the last write data when write_index is b1111                           // else if (&(write_index[C_TRANSACTIONS_NUM-1:1])&& ~write_index[0] && wnext)  else if (((write_index == C_M_AXI_BURST_LEN-2 && C_M_AXI_BURST_LEN >= 2) && wnext) || (C_M_AXI_BURST_LEN == 1 ))begin                                                                         axi_wlast <= 1'b1;                                                          end                                                                           // Deassrt axi_wlast when the last write data has been                          // accepted by the slave with a valid response                                  else if (wnext)                                                                 axi_wlast <= 1'b0;                                                            else if (axi_wlast && C_M_AXI_BURST_LEN == 1)                                   axi_wlast <= 1'b0;                                                            else                                                                            axi_wlast <= axi_wlast;                                                       end                                                                               /* Burst length counter. Uses extra counter register bit to indicate terminal       count to reduce decode logic */                                                    always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 || start_single_burst_write == 1'b1)    begin                                                                         write_index <= 0;                                                           end                                                                           else if (wnext && (write_index != C_M_AXI_BURST_LEN-1))                         begin                                                                         write_index <= write_index + 1;                                             end                                                                           else                                                                            write_index <= write_index;                                                   end                                                                               /* Write Data Generator                                                             Data pattern is only a simple incrementing count from 0 for each burst  */         always @(posedge M_AXI_ACLK)                                                      begin                                                                             if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                         axi_wdata <= 'b1;                                                             //else if (wnext && axi_wlast)                                                  //  axi_wdata <= 'b0;                                                           else if (wnext)                                                                 axi_wdata <= axi_wdata + 1;                                                   else                                                                            axi_wdata <= axi_wdata;                                                       end                                

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

        写响应准备信号axi_bready:当从机发送的M_AXI_BVALID有效时,将其拉高。

写响应错误信号write_resp_error:当接收的写响应有误时,将其拉高。

   always @(posedge M_AXI_ACLK)                                     begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                            begin                                                             axi_bready <= 1'b0;                                             end                                                               // accept/acknowledge bresp with axi_bready by the master           // when M_AXI_BVALID is asserted by slave                           else if (M_AXI_BVALID && ~axi_bready)                               begin                                                             axi_bready <= 1'b1;                                             end                                                               // deassert after one clock cycle                                   else if (axi_bready)                                                begin                                                             axi_bready <= 1'b0;                                             end                                                               // retain the previous value                                        else                                                                axi_bready <= axi_bready;                                         end                                                                   //Flag any write response errors                                        assign write_resp_error = axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]; 

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

        读地址准备信号axi_arvalid:当单次突发读信号start_single_burst_read有效时,将其拉高。

读地址通道握手成功时同时对首地址axi_araddr赋值。

   always @(posedge M_AXI_ACLK)                                 begin                                                              if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                         begin                                                          axi_arvalid <= 1'b0;                                         end                                                            // If previously not valid , start next transaction              else if (~axi_arvalid && start_single_burst_read)                begin                                                          axi_arvalid <= 1'b1;                                         end                                                            else if (M_AXI_ARREADY && axi_arvalid)                           begin                                                          axi_arvalid <= 1'b0;                                         end                                                            else                                                             axi_arvalid <= axi_arvalid;                                    end                                                                // Next address after ARREADY indicates previous address acceptance  always @(posedge M_AXI_ACLK)                                       begin                                                              if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                          begin                                                          axi_araddr <= 'b0;                                           end                                                            else if (M_AXI_ARREADY && axi_arvalid)                           begin                                                          axi_araddr <= axi_araddr + burst_size_bytes;                 end                                                            else                                                             axi_araddr <= axi_araddr;                                      end             

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

        读数据准备信号axi_rready:当完成最后一个数据的读取后拉低,当从机发送的读有效信号M_AXI_RVALID有效时将其拉高。

每读取一个数据,突发读取长度计数器read_index累加1。

读不匹配信号read_mismatch:当读取数据与预期读取数据(写入的数据)不一致时,将其拉高。

读响应错误信号read_resp_error:一旦读取响应值非法就将其拉高。

预期读取数据expected_rdata:预期读到的数据,即写入数据。

错误信号error_reg:一旦满足以下三种错误即拉高:1、写响应错误;2、读响应错误;3、读、写内容不匹配。

  // Forward movement occurs when the channel is valid and ready   assign rnext = M_AXI_RVALID && axi_rready;           //读数据期间                       // Burst length counter. Uses extra counter register bit to indicate    // terminal count to reduce decode logic                                always @(posedge M_AXI_ACLK)                                          begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 || start_single_burst_read)                  begin                                                             read_index <= 0;                                                end                                                               else if (rnext && (read_index != C_M_AXI_BURST_LEN-1))              begin                                                             read_index <= read_index + 1;                                   end                                                               else                                                                read_index <= read_index;                                         end                                                                   /*                                                                      The Read Data channel returns the results of the read request          In this example the data checker is always able to accept              more data, so no need to throttle the RREADY signal                    */                                                                     always @(posedge M_AXI_ACLK)                                          begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                  begin                                                             axi_rready <= 1'b0;                                             end                                                               // accept/acknowledge rdata/rresp with axi_rready by the master     // when M_AXI_RVALID is asserted by slave                           else if (M_AXI_RVALID)                       begin                                      if (M_AXI_RLAST && axi_rready)          begin                                  axi_rready <= 1'b0;                  end                                    else                                    begin                                 axi_rready <= 1'b1;                 end                                   end                                        // retain the previous value                 end                                            //Check received read data against data generator                       always @(posedge M_AXI_ACLK)                                          begin                                                                 if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                   begin                                                             read_mismatch <= 1'b0;                                          end                                                               //Only check data when RVALID is active                             else if (rnext && (M_AXI_RDATA != expected_rdata))                  begin                                                             read_mismatch <= 1'b1;                                          end                                                               else                                                                read_mismatch <= 1'b0;                                            end                                                                   //Flag any read response errors                                         assign read_resp_error = axi_rready & M_AXI_RVALID & M_AXI_RRESP[1]; //----------------------------------------//Example design read check data generator//-----------------------------------------//Generate expected read data to check against actual read dataalways @(posedge M_AXI_ACLK)                     begin                                                  if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)// || M_AXI_RLAST)             expected_rdata <= 'b1;                            else if (M_AXI_RVALID && axi_rready)                  expected_rdata <= expected_rdata + 1;             else                                                  expected_rdata <= expected_rdata;                 end  //----------------------------------//Example design error register//----------------------------------//Register and hold any data mismatches, or read/write interface errors always @(posedge M_AXI_ACLK)                                 begin                                                              if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                          begin                                                          error_reg <= 1'b0;                                           end                                                            else if (read_mismatch || write_resp_error || read_resp_error)   begin                                                          error_reg <= 1'b1;                                           end                                                            else                                                             error_reg <= error_reg;                                        end  

NO.10----读、写突发长度计数:

        读、写突发长度计数信号read_burst_counter、write_burst_counter在读写期间统计读、写的个数。

  // write_burst_counter counter keeps track with the number of burst transaction initiated            // against the number of burst transactions the master needs to initiate                                   always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )                                                                                 begin                                                                                                 write_burst_counter <= 'b0;                                                                         end                                                                                                   else if (M_AXI_AWREADY && axi_awvalid)                                                                  begin                                                                                                 if (write_burst_counter[C_NO_BURSTS_REQ] == 1'b0)                                                   begin                                                                                             write_burst_counter <= write_burst_counter + 1'b1;                                              //write_burst_counter[C_NO_BURSTS_REQ] <= 1'b1;                                                 end                                                                                               end                                                                                                   else                                                                                                    write_burst_counter <= write_burst_counter;                                                           end                                                                                                       // read_burst_counter counter keeps track with the number of burst transaction initiated                   // against the number of burst transactions the master needs to initiate                                   always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 begin                                                                                                 read_burst_counter <= 'b0;                                                                          end                                                                                                   else if (M_AXI_ARREADY && axi_arvalid)                                                                  begin                                                                                                 if (read_burst_counter[C_NO_BURSTS_REQ] == 1'b0)                                                    begin                                                                                             read_burst_counter <= read_burst_counter + 1'b1;                                                //read_burst_counter[C_NO_BURSTS_REQ] <= 1'b1;                                                  end                                                                                               end                                                                                                   else                                                                                                    read_burst_counter <= read_burst_counter;                                                             end

NO.11----流程控制状态机:

        该状态机有4个状态:

IDLE:初始状态,一旦写事务开始信号init_txn_pulse有效,即进入写事务状态INIT_WRITE

INIT_WRITE:写事务状态,在此状态完成64次长度为16的突发写事务。一旦所有写事务完成,即进入读事务状态INIT_READ

INIT_READ:读事务状态,在此状态完成64次长度为16的突发读事务。一旦所有读事务完成,即进入比较状态INIT_COMPARE

INIT_COMPARE:比较状态(比较错误),判断是否存在错误情况(读写不匹配、写响应错误或读响应错误),然后跳转回初始状态IDLE

   //implement master command interface state machine                                                        always @ ( posedge M_AXI_ACLK)                                                                            begin                                                                                                     if (M_AXI_ARESETN == 1'b0 )                                                                             begin                                                                                                 // reset condition                                                                                  // All the signals are assigned default values under reset condition                                mst_exec_state      <= IDLE;                                                                start_single_burst_write <= 1'b0;                                                                   start_single_burst_read  <= 1'b0;                                                                   compare_done      <= 1'b0;                                                                          ERROR <= 1'b0;   end                                                                                                   else                                                                                                    begin                                                                                                 // state transition                                                                                 case (mst_exec_state)                                                                               IDLE:                                                                                     // This state is responsible to wait for user defined C_M_START_COUNT                           // number of clock cycles.                                                                      if ( init_txn_pulse == 1'b1)                                                      begin                                                                                         mst_exec_state  <= INIT_WRITE;                                                              ERROR <= 1'b0;compare_done <= 1'b0;end                                                                                           else                                                                                            begin                                                                                         mst_exec_state  <= IDLE;                                                            end                                                                                           INIT_WRITE:                                                                                       // This state is responsible to issue start_single_write pulse to                               // initiate a write transaction. Write transactions will be                                     // issued until burst_write_active signal is asserted.                                          // write controller                                                                             if (writes_done)                                                                                begin                                                                                         mst_exec_state <= INIT_READ;//                                                              end                                                                                           else                                                                                            begin                                                                                         mst_exec_state  <= INIT_WRITE;                                                              if (~axi_awvalid && ~start_single_burst_write && ~burst_write_active)                       begin                                                                                     start_single_burst_write <= 1'b1;                                                       end                                                                                       else                                                                                        begin                                                                                     start_single_burst_write <= 1'b0; //Negate to generate a pulse                          end                                                                                       end                                                                                           INIT_READ:                                                                                        // This state is responsible to issue start_single_read pulse to                                // initiate a read transaction. Read transactions will be                                       // issued until burst_read_active signal is asserted.                                           // read controller                                                                              if (reads_done)                                                                                 begin                                                                                         mst_exec_state <= INIT_COMPARE;                                                             end                                                                                           else                                                                                            begin                                                                                         mst_exec_state  <= INIT_READ;                                                               if (~axi_arvalid && ~burst_read_active && ~start_single_burst_read)                         begin                                                                                     start_single_burst_read <= 1'b1;                                                        end                                                                                       else                                                                                         begin                                                                                      start_single_burst_read <= 1'b0; //Negate to generate a pulse                            end                                                                                        end                                                                                           INIT_COMPARE:                                                                                     // This state is responsible to issue the state of comparison                                   // of written data with the read data. If no error flags are set,                               // compare_done signal will be asseted to indicate success.                                     //if (~error_reg)                                                                               begin                                                                                           ERROR <= error_reg;mst_exec_state <= IDLE;                                                               compare_done <= 1'b1;                                                                         end                                                                                             default :                                                                                         begin                                                                                           mst_exec_state  <= IDLE;                                                              end                                                                                             endcase                                                                                             end                                                                                                   end //MASTER_EXECUTION_PROC

NO.11----突发读写状态管理:

burst_write_active:突发写有效信号,其拉高即表示,正在进行一次突发写过程

burst_read_active:突发读有效信号,其拉高即表示,正在进行一次突发读过程

writes_done:全部写事务完成信号,完成所有写事务后将其拉高

reads_done:全部读事务完成信号,完成所有读事务后将其拉高

   // burst_write_active signal is asserted when there is a burst write transaction                          // is initiated by the assertion of start_single_burst_write. burst_write_active                          // signal remains asserted until the burst write is accepted by the slave                                 always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 burst_write_active <= 1'b0;                                                                           //The burst_write_active is asserted when a write burst transaction is initiated                        else if (start_single_burst_write)                                                                      burst_write_active <= 1'b1;                                                                           else if (M_AXI_BVALID && axi_bready)                                                                    burst_write_active <= 0;                                                                              end                                                                                                       // Check for last write completion.                                                                        // This logic is to qualify the last write count with the final write                                      // response. This demonstrates how to confirm that a write has been                                        // committed.                                                                                              always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 writes_done <= 1'b0;                                                                                  //The writes_done should be associated with a bready response                                           //else if (M_AXI_BVALID && axi_bready && (write_burst_counter == {(C_NO_BURSTS_REQ-1){1}}) && axi_wlast)else if (M_AXI_BVALID && (write_burst_counter[C_NO_BURSTS_REQ]) && axi_bready)                          writes_done <= 1'b1;                                                                                  else                                                                                                    writes_done <= writes_done;                                                                           end                                                                                                     // burst_read_active signal is asserted when there is a burst write transaction                           // is initiated by the assertion of start_single_burst_write. start_single_burst_read                     // signal remains asserted until the burst read is accepted by the master                                 always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 burst_read_active <= 1'b0;                                                                            //The burst_write_active is asserted when a write burst transaction is initiated                        else if (start_single_burst_read)                                                                       burst_read_active <= 1'b1;                                                                            else if (M_AXI_RVALID && axi_rready && M_AXI_RLAST)                                                     burst_read_active <= 0;                                                                               end                                                                                                     // Check for last read completion.                                                                         // This logic is to qualify the last read count with the final read                                        // response. This demonstrates how to confirm that a read has been                                         // committed.                                                                                              always @(posedge M_AXI_ACLK)                                                                              begin                                                                                                     if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)                                                                                 reads_done <= 1'b0;                                                                                   //The reads_done should be associated with a rready response                                            //else if (M_AXI_BVALID && axi_bready && (write_burst_counter == {(C_NO_BURSTS_REQ-1){1}}) && axi_wlast)else if (M_AXI_RVALID && axi_rready && (read_index == C_M_AXI_BURST_LEN-1) && (read_burst_counter[C_NO_BURSTS_REQ]))reads_done <= 1'b1;                                                                                   else                                                                                                    reads_done <= reads_done;                                                                             end                                                                                                     // Add user logic here// User logic endsendmodule

3、仿真波形

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

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

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

仿真结果如下:

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

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

在左键点击,会显示具体的事务流程如下:写地址----写数据----写响应。

再把鼠标放到最后一次读事务上,观察读事务的相关信息,如下:

可以看到,最后一次读事务的相关信息与最后一次写事务的相关信息是一致的,这表示写入数据与读出数据理论上一致。

再点击这次读事务,观察其实现过程:读地址----读数据(包含读响应)。

3.2、主机IP的master接口仿真波形

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

将信号按通道或用途做好分类,写事务(一共有64次写事务,限于篇幅,仅截图2次写事务)的仿真结果如下:

读事务(一共有64次读事务,限于篇幅,仅截图2次读事务)的仿真结果如下:

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

4、其他

  • 可以看到其实AXI4-Full总线的使用还是相对比较简单的,只要设计好各个通道的握手时序,以及读写的时序关系就好了。AXI4这个系列暂时就结束了。
  • 创作不易,希望各位大佬多多三连支持!一家之言,如有错误还请指正!

版本信息

文件:V1.0

编号:67

Vivado:Vivado 2019.2

Modelsim:无

Quartus II:无

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

最新文章

  1. openlayers map获取全部feature_tf2.0基础-tf.data与tf.feature_column
  2. 放弃深圳1.5万月薪,我准备回农村了!
  3. 江苏省有JAVA技能大赛,江苏省职业学校技能大赛组委会
  4. SpringMVC4 实例
  5. Red Hat Enterprise Linux上配置SQL Server Always On Availability Group
  6. 机器人学导论原书第三版
  7. 超级玛丽制作揭秘8跟踪打印 类FILEREPORT
  8. 黑马Java基础笔记大纲
  9. 检查服务器端口占用,服务器中如何检查端口是否开放
  10. mivo tv android,MivoTV Live Streaming
  11. 2018厦门大学计算机技术分数线,厦门大学2018年各省市录取分数线
  12. Graph Convolutional Matrix Completion,GC-MC
  13. Android,上传一张本地图片到服务器,Okhttp的post请求上传图片本地服务器
  14. Python数据分析入门书籍推荐!!!强烈推荐,新手必看
  15. 古罗马的幽灵--斗兽场
  16. 使用TreeMap实现ASCII排序
  17. Pandas中multiindex转换成列
  18. VMware Workstation 不可恢复错误: (vcpu-0) vcpu-0:VERIFY vmcore/vmm/main/physMem_monitor.c:1123
  19. java 读取网页 获取内容导入到本地生成word 网页转word
  20. 华为数据通信、光网络系列产品通过MEF电信级以太网认证

热门文章

  1. 分享一个公众号h5裂变吸粉源码工具
  2. js 实现登录成功 首页显示用户名和退出登录
  3. R语言手动绘制分类Logistic回归模型的校准曲线(Calibration curve)(3)
  4. 每月 5 号发工资和 25 号发工资,真能看出公司是否靠谱?
  5. 关于下载cuda和cudnn官方网站访问不了的替代方案
  6. 不会拒绝,就等于不会做工作。拒绝不合理要求的五个关键
  7. 趣拍CEO王强宇演讲实录
  8. KMSAuto Net 2016 1.4.9 Portable
  9. 手写Vue个人组件库——fl-Breadcrumb
  10. 以信息化建设为抓手,推出职业病危害因素在线监测平台,保障劳动者健康工作