一,在XIINX FPGA中有支持三种AXI总线,有三种AXI协议接口,全局时钟,复位低有效分别是
AXI4:面向高性能地址映射通信需求,是面向地址映射的接口,最大允许256次的数据突发传输;
AXI4-Lite:是一个轻量级的地址映射单次传输接口,占用很少的逻辑单元。
AXI4-Stream:面向高速流数据传输;去掉了地址项,允许无限制的数据突发传输规模。
1,写地址通道信号

2,写数据和写响应信号

3,读地址通道号

4,读数据通道号

二,AXI4-Lite搭建hp接口
1,单击菜单栏 Tools->Create and Package New IP,开始创建一个AXI4-Lite接口总线IP

2,使用vivado自带的AXI总线模板创建一个AXI4-Lite接口IP,并命名


3,模板支持三种协议,lite/full/stream,总线包括Master和Slave两种接口模式,这里根据自己的搭建目标选择Master模式或Slave模式。


这里选择axi_lite_master,搭建HP接口。

4,编辑接口进行用户代码添加

5,在module pl_to_ps_hp_v1_0 #模块中,第20行,// Users to add ports here地方,添加输入和输出接口。这里input是留给PL直接输入数据的地方。
input wire pl_to_ps_wr_valid,
input wire [63:0]wr_pl_to_ps_hp_data,
output wire ps_to_pl_rd_valid,
output wire [63:0]rd_ps_to_pl_hp_data,
input wire wr_base_addr_valid,
input wire [31:0]wr_base_addr,
input wire rd_base_addr_valid,
input wire [31:0]rd_base_addr,
input wire [15:0]rd_length,
6,在module pl_to_ps_hp_v1_0 #模块中,在// Instantiation of Axi Bus Interface M00_AXI注释下面的pl_to_ps_hp_v1_0_M00_AXI #中的例化末尾加入例化的接口,具体例化对象就是上面的输入输出信号,具体如下:
- pl_to_ps_hp_v1_0_M00_AXI # (
- .C_M_START_DATA_VALUE(C_M00_AXI_START_DATA_VALUE),
- .C_M_TARGET_SLAVE_BASE_ADDR(C_M00_AXI_TARGET_SLAVE_BASE_ADDR),
- .C_M_AXI_ADDR_WIDTH(C_M00_AXI_ADDR_WIDTH),
- .C_M_AXI_DATA_WIDTH(C_M00_AXI_DATA_WIDTH),
- .C_M_TRANSACTIONS_NUM(C_M00_AXI_TRANSACTIONS_NUM)
- ) pl_to_ps_hp_v1_0_M00_AXI_inst (
- .INIT_AXI_TXN(m00_axi_init_axi_txn),
- .ERROR(m00_axi_error),
- .TXN_DONE(m00_axi_txn_done),
- .M_AXI_ACLK(m00_axi_aclk),
- .M_AXI_ARESETN(m00_axi_aresetn),
- .M_AXI_AWADDR(m00_axi_awaddr),
- .M_AXI_AWPROT(m00_axi_awprot),
- .M_AXI_AWVALID(m00_axi_awvalid),
- .M_AXI_AWREADY(m00_axi_awready),
- .M_AXI_WDATA(m00_axi_wdata),
- .M_AXI_WSTRB(m00_axi_wstrb),
- .M_AXI_WVALID(m00_axi_wvalid),
- .M_AXI_WREADY(m00_axi_wready),
- .M_AXI_BRESP(m00_axi_bresp),
- .M_AXI_BVALID(m00_axi_bvalid),
- .M_AXI_BREADY(m00_axi_bready),
- .M_AXI_ARADDR(m00_axi_araddr),
- .M_AXI_ARPROT(m00_axi_arprot),
- .M_AXI_ARVALID(m00_axi_arvalid),
- .M_AXI_ARREADY(m00_axi_arready),
- .M_AXI_RDATA(m00_axi_rdata),
- .M_AXI_RRESP(m00_axi_rresp),
- .M_AXI_RVALID(m00_axi_rvalid),
- .M_AXI_RREADY(m00_axi_rready),
- .wr_base_addr_valid(wr_base_addr_valid),
- .wr_base_addr(wr_base_addr),
- .rd_base_addr_valid(rd_base_addr_valid),
- .rd_base_addr(rd_base_addr),
- .rd_length(rd_length),
- .pl_to_ps_wr_valid(pl_to_ps_wr_valid),
- .wr_pl_to_ps_hp_data(wr_pl_to_ps_hp_data),
- .rd_ps_to_pl_hp_data(rd_ps_to_pl_hp_data),
- .rd_ps_to_pl_hp_data(rd_ps_to_pl_hp_data)
- );
7,在module pl_to_ps_hp_v1_0_M00_AXI #模块中,输入输出接口的地方,第30行加入输入输出信号,都是从它的顶层文件引入进来的。
- module pl_to_ps_hp_v1_0_M00_AXI #
- (
- // Users to add parameters here
-
- // User parameters ends
- // Do not modify the parameters beyond this line
-
- // The master will start generating data from the C_M_START_DATA_VALUE value
- parameter C_M_START_DATA_VALUE = 32'hAA000000,
- // The master requires a target slave base address.
- // The master will initiate read and write transactions on the slave with base address specified here as a parameter.
- parameter C_M_TARGET_SLAVE_BASE_ADDR = 32'h40000000,
- // Width of M_AXI address bus.
- // The master generates the read and write addresses of width specified as C_M_AXI_ADDR_WIDTH.
- parameter integer C_M_AXI_ADDR_WIDTH = 32,
- // Width of M_AXI data bus.
- // The master issues write data and accept read data where the width of the data bus is C_M_AXI_DATA_WIDTH
- parameter integer C_M_AXI_DATA_WIDTH = 32,
- // Transaction number is the number of write
- // and read transactions the master will perform as a part of this example memory test.
- parameter integer C_M_TRANSACTIONS_NUM = 4
- )
- (
- // Users to add ports here
-
- // User ports ends
- input wire wr_base_addr_valid,
- input wire [31:0]wr_base_addr,
- input wire rd_base_addr_valid,
- input wire [31:0]rd_base_addr,
- input wire [15:0]rd_length,
- input wire pl_to_ps_wr_valid,
- input wire [63:0]wr_pl_to_ps_hp_data,
- output reg ps_to_pl_rd_valid,
- output reg [63:0]rd_ps_to_pl_hp_data,
- // Do not modify the ports beyond this line
-
- // Initiate AXI transactions
- input wire INIT_AXI_TXN,
- // Asserts when ERROR is detected
- output reg ERROR,
- // Asserts when AXI transactions is complete
- output wire TXN_DONE,
- // AXI clock signal
- input wire M_AXI_ACLK,
- // AXI active low reset signal
- input wire M_AXI_ARESETN,
- // Master Interface Write Address Channel ports. Write address (issued by master)
- output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,
- // Write channel 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,
- // Write address valid.
- // This signal indicates that the master 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 signals.
- input wire M_AXI_AWREADY,
- // Master Interface Write Data Channel ports. Write data (issued by master)
- 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 valid. This signal indicates that valid write data and strobes are available.
- output 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 Channel ports.
- // This signal indicates the status of the write transaction.
- input wire [1 : 0] M_AXI_BRESP,
- // 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 Channel ports. Read address (issued by master)
- output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR,
- // 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,
- // Read address valid.
- // This signal indicates that the channel is signaling valid read address and control information.
- output wire M_AXI_ARVALID,
- // Read address ready.
- // This signal indicates that the slave is ready to accept an address and associated control signals.
- input wire M_AXI_ARREADY,
- // Master Interface Read Data Channel ports. Read data (issued by slave)
- input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA,
- // Read response. This signal indicates the status of the read transfer.
- input wire [1 : 0] M_AXI_RRESP,
- // 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
- );
8,在module pl_to_ps_hp_v1_0_M00_AXI #模块中,把下面引入数据的内容都换成具体的有效信号,地址信号或者数据信号。官方生成的接口传的是固定地址32'h40000000和固定数据32'hAA000000。修改为:
- reg axi_awvalid; //write address valid
- reg axi_wvalid; //write data valid
- reg axi_arvalid; //read address valid
- reg axi_bready=1'b0; //write response acceptance
- reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_awaddr; //write address
- reg [C_M_AXI_DATA_WIDTH-1 : 0] axi_wdata; //write data
- reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_araddr; //read addresss
- reg [15 : 0]read_index;
- assign M_AXI_AWADDR = axi_awaddr;
- assign M_AXI_WDATA = axi_wdata;
- assign M_AXI_AWPROT = 3'b000;
- assign M_AXI_AWVALID = axi_awvalid;
- assign M_AXI_WVALID = axi_wvalid;
- assign M_AXI_WSTRB = 8'b11111111;
- assign M_AXI_BREADY = axi_bready;
- assign M_AXI_ARADDR = axi_araddr;
- assign M_AXI_ARVALID= axi_arvalid;
- assign M_AXI_ARPROT = 3'b001;
- assign M_AXI_RREADY = ps_to_pl_rd_valid;
-
- //--------------------------------
- //用户的编辑思路
- //--------------------------------
- reg [31:0]axi_awaddr_r=32'd0;
- always @(posedge M_AXI_ACLK)
- begin
- if(wr_base_addr_valid)
- begin //锁存写数据基地址
- axi_awaddr_r <= wr_base_addr;
- end
- else if(M_AXI_AWREADY&&M_AXI_WREADY&& pl_to_ps_wr_valid)
- begin //PL TO PS HP写数据过程
- axi_awvalid <= 1'b1;
- axi_awaddr <= axi_awaddr_r;
- axi_awaddr_r <= axi_awaddr_r + 32'h00000008;
- axi_wvalid <= 1'b1;
- axi_wdata <= wr_pl_to_ps_hp_data;
- end
- else
- begin
- axi_awvalid <= 1'b0;
- axi_wvalid <= 1'b0;
- end
- end
- always @(posedge M_AXI_ACLK) //产生回应信号
- begin
- if(M_AXI_BVALID&&(!axi_bready))
- begin
- axi_bready <= 1'b1;
- end
- else if(axi_bready)begin
- axi_bready <= 1'b0;
- end
- else
- begin
- axi_bready <= axi_bready;
- end
- end
-
- reg [1:0]rd_state;
- reg [31:0]axi_araddr_r;
- always @(posedge M_AXI_ACLK)
- begin
- if(M_AXI_ARESETN == 0)
- begin
- rd_state <= 2'd0;
- read_index <= 16'd0;
- axi_araddr <= 32'd0;
- axi_araddr_r <= 32'd0;
- axi_arvalid <= 1'b0;
- ps_to_pl_rd_valid <= 1'b0;
- rd_ps_to_pl_hp_data <= 64'h0;
- end
- else begin
- case(rd_state)
- 2'd0:
- begin
- if(rd_base_addr_valid)begin
- axi_araddr_r <= rd_base_addr;
- read_index <= 16'd0;
- rd_state <= rd_state + 1'b1;
- end
- else
- begin
- rd_state <= rd_state;
- end
- end
- 2'd1:begin
- if(M_AXI_ARREADY)
- begin
- axi_arvalid <= 1'b1;
- axi_araddr <= axi_araddr_r;
- axi_araddr_r <= axi_araddr_r + 32'h00000008;
- read_index <= read_index + 1;
- rd_state <= rd_state + 1'b1;
- end
- else
- begin
- axi_arvalid <= 1'b0;
- end
- end
- 2'd2:begin
- axi_arvalid <= 1'b0;
- if(M_AXI_RVALID)
- begin
- ps_to_pl_rd_valid <= 1'b1;
- rd_ps_to_pl_hp_data <= M_AXI_RDATA;
- rd_state <= rd_state + 1'b1;
- end
- else begin
- rd_state <= rd_state;
- end
- end
- 2'd3:
- begin
- ps_to_pl_rd_valid <= 1'b0;
- if(read_index==rd_length)begin
- rd_state <= 2'd0;
- end
- else begin
- rd_state <= 2'd1;
- end
- end
- endcase
- end
- end
9,生成bit流就可以正式使用了

三,搭建hp接口的block design
四,zynq sdk读写HP DDR验证
五,选择Verify Peripheral IP using AXI4 VIP可以自行对AXI4-lite快速验证


单击完成后vivado自动产生demo,单击Block Design的工程,可以看到如下 2 个 IP。其中 maxi_lite_0就是我自定义的IP,另外一个slave_0是用来验证 maxi_lite_0正确性。

采用默认地址分配0x44A0_0000

axi_lite_master代码解析:

- `timescale 1 ns / 1 ps
- module maxi_lite_v1_0_M00_AXI #
- (
- // Users to add parameters here
- // User parameters ends
- // Do not modify the parameters beyond this line
- // The master will start generating data from the C_M_START_DATA_VALUE value
- parameter C_M_START_DATA_VALUE = 32'hAA000000,
- // The master requires a target slave base address.
- // The master will initiate read and write transactions on the slave with base address specified here as a parameter.
- parameter C_M_TARGET_SLAVE_BASE_ADDR = 32'h40000000,
- // Width of M_AXI address bus.
- // The master generates the read and write addresses of width specified as C_M_AXI_ADDR_WIDTH.
- parameter integer C_M_AXI_ADDR_WIDTH = 32,
- // Width of M_AXI data bus.
- // The master issues write data and accept read data where the width of the data bus is C_M_AXI_DATA_WIDTH
- parameter integer C_M_AXI_DATA_WIDTH = 32,
- // Transaction number is the number of write
- // and read transactions the master will perform as a part of this example memory test.
- parameter integer C_M_TRANSACTIONS_NUM = 4
- )
- (
- // Users to add ports here
- // User ports ends
- // Do not modify the ports beyond this line
- // Initiate AXI transactions
- input wire INIT_AXI_TXN,
- // Asserts when ERROR is detected
- output reg ERROR,
- // Asserts when AXI transactions is complete
- output wire TXN_DONE,
- // AXI clock signal
- input wire M_AXI_ACLK,
- // AXI active low reset signal
- input wire M_AXI_ARESETN,
- // Master Interface Write Address Channel ports. Write address (issued by master)
- output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_AWADDR,
- // Write channel 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,
- // Write address valid.
- // This signal indicates that the master 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 signals.
- input wire M_AXI_AWREADY,
- // Master Interface Write Data Channel ports. Write data (issued by master)
- 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 valid. This signal indicates that valid write data and strobes are available.
- output 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 Channel ports.
- // This signal indicates the status of the write transaction.
- input wire [1 : 0] M_AXI_BRESP,
- // 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 Channel ports. Read address (issued by master)
- output wire [C_M_AXI_ADDR_WIDTH-1 : 0] M_AXI_ARADDR,
- // 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,
- // Read address valid.
- // This signal indicates that the channel is signaling valid read address and control information.
- output wire M_AXI_ARVALID,
- // Read address ready.
- // This signal indicates that the slave is ready to accept an address and associated control signals.
- input wire M_AXI_ARREADY,
- // Master Interface Read Data Channel ports. Read data (issued by slave)
- input wire [C_M_AXI_DATA_WIDTH-1 : 0] M_AXI_RDATA,
- // Read response. This signal indicates the status of the read transfer.
- input wire [1 : 0] M_AXI_RRESP,
- // 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
- );
-
- // 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
- // TRANS_NUM_BITS is the width of the index counter for
- // number of write or read transaction.
- localparam integer TRANS_NUM_BITS = clogb2(C_M_TRANSACTIONS_NUM-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_TXN
- INIT_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
- //write address valid
- reg axi_awvalid;
- //write data valid
- reg axi_wvalid;
- //read address valid
- reg axi_arvalid;
- //read data acceptance
- reg axi_rready;
- //write response acceptance
- reg axi_bready;
- //write address
- reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_awaddr;
- //write data
- reg [C_M_AXI_DATA_WIDTH-1 : 0] axi_wdata;
- //read addresss
- reg [C_M_AXI_ADDR_WIDTH-1 : 0] axi_araddr;
- //Asserts when there is a write response error
- wire write_resp_error;
- //Asserts when there is a read response error
- wire read_resp_error;
- //A pulse to initiate a write transaction
- reg start_single_write;
- //A pulse to initiate a read transaction
- reg start_single_read;
- //Asserts when a single beat write transaction is issued and remains asserted till the completion of write trasaction.
- reg write_issued;
- //Asserts when a single beat read transaction is issued and remains asserted till the completion of read trasaction.
- reg read_issued;
- //flag that marks the completion of write trasactions. The number of write transaction is user selected by the parameter C_M_TRANSACTIONS_NUM.
- reg writes_done;
- //flag that marks the completion of read trasactions. The number of read transaction is user selected by the parameter C_M_TRANSACTIONS_NUM
- reg reads_done;
- //The error register is asserted when any of the write response error, read response error or the data mismatch flags are asserted.
- reg error_reg;
- //index counter to track the number of write transaction issued
- reg [TRANS_NUM_BITS : 0] write_index;
- //index counter to track the number of read transaction issued
- reg [TRANS_NUM_BITS : 0] read_index;
- //Expected read data used to compare with the read data.
- reg [C_M_AXI_DATA_WIDTH-1 : 0] expected_rdata;
- //Flag marks the completion of comparison of the read data with the expected read data
- reg compare_done;
- //This flag is asserted when there is a mismatch of the read data with the expected read data.
- reg read_mismatch;
- //Flag is asserted when the write index reaches the last write transction number
- reg last_write;
- //Flag is asserted when the read index reaches the last read transction number
- reg last_read;
- reg init_txn_ff;
- reg init_txn_ff2;
- reg init_txn_edge;
- wire init_txn_pulse;
- // I/O Connections assignments
- //Adding the offset address to the base addr of the slave
- assign M_AXI_AWADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_awaddr;
- //AXI 4 write data
- assign M_AXI_WDATA = axi_wdata;
- assign M_AXI_AWPROT = 3'b000;
- assign M_AXI_AWVALID = axi_awvalid;
- //Write Data(W)
- assign M_AXI_WVALID = axi_wvalid;
- //Set all byte strobes in this example
- assign M_AXI_WSTRB = 4'b1111;
- //Write Response (B)
- assign M_AXI_BREADY = axi_bready;
- //Read Address (AR)
- assign M_AXI_ARADDR = C_M_TARGET_SLAVE_BASE_ADDR + axi_araddr;
- assign M_AXI_ARVALID = axi_arvalid;
- assign M_AXI_ARPROT = 3'b001;
- //Read and Read Response (R)
- assign M_AXI_RREADY = axi_rready;
- //Example design I/O
- assign TXN_DONE = compare_done;
- 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
-
- //--------------------
- //Write Address Channel
- //--------------------
-
- // The purpose of the write address channel is to request the address and
- // command information for the entire transaction. It is a single beat
- // of information.
- // Note for this example the axi_awvalid/axi_wvalid are asserted at the same
- // time, and then each is deasserted independent from each other.
- // This is a lower-performance, but simplier control scheme.
- // AXI VALID signals must be held active until accepted by the partner.
- // A data transfer is accepted by the slave when a master has
- // VALID data and the slave acknoledges it is also READY. While the master
- // is allowed to generated multiple, back-to-back requests by not
- // deasserting VALID, this design will add rest cycle for
- // simplicity.
- // Since only one outstanding transaction is issued by the user design,
- // there will not be a collision between a new request and an accepted
- // request on the same clock cycle.
- always @(posedge M_AXI_ACLK)
- begin
- //Only VALID signals must be deasserted during reset per AXI spec
- //Consider inverting then registering active-low reset for higher fmax
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- axi_awvalid <= 1'b0;
- end
- //Signal a new address/data command is available by user logic
- else
- begin
- if (start_single_write)
- begin
- axi_awvalid <= 1'b1;
- end
- //Address accepted by interconnect/slave (issue of M_AXI_AWREADY by slave)
- else if (M_AXI_AWREADY && axi_awvalid)
- begin
- axi_awvalid <= 1'b0;
- end
- end
- end
-
- // start_single_write triggers a new write
- // transaction. write_index is a counter to
- // keep track with number of write transaction
- // issued/initiated
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- write_index <= 0;
- end
- // Signals a new write address/ write data is
- // available by user logic
- else if (start_single_write)
- begin
- write_index <= write_index + 1;
- end
- end
-
- //--------------------
- //Write Data Channel
- //--------------------
- //The write data channel is for transfering the actual data.
- //The data generation is speific to the example design, and
- //so only the WVALID/WREADY handshake is shown here
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- axi_wvalid <= 1'b0;
- end
- //Signal a new address/data command is available by user logic
- else if (start_single_write)
- begin
- axi_wvalid <= 1'b1;
- end
- //Data accepted by interconnect/slave (issue of M_AXI_WREADY by slave)
- else if (M_AXI_WREADY && axi_wvalid)
- begin
- axi_wvalid <= 1'b0;
- end
- end
- //----------------------------
- //Write Response (B) Channel
- //----------------------------
- //The write response channel provides feedback that the write has committed
- //to memory. BREADY will occur after both the data and the write address
- //has arrived and been accepted by the slave, and can guarantee that no
- //other accesses launched afterwards will be able to be reordered before it.
-
- //The BRESP bit [1] is used indicate any errors from the interconnect or
- //slave for the entire write burst. This example will capture the error.
- //While not necessary per spec, it is advisable to reset READY signals in
- //case of differing reset latencies between master/slave.
- 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 write errors
- assign write_resp_error = (axi_bready & M_AXI_BVALID & M_AXI_BRESP[1]);
-
- //----------------------------
- //Read Address Channel
- //----------------------------
- //start_single_read triggers a new read transaction. read_index is a counter to
- //keep track with number of read transaction issued/initiated
-
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- read_index <= 0;
- end
- // Signals a new read address is
- // available by user logic
- else if (start_single_read)
- begin
- read_index <= read_index + 1;
- end
- end
-
- // A new axi_arvalid is asserted when there is a valid read address
- // available by the master. start_single_read triggers a new read
- // transaction
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- axi_arvalid <= 1'b0;
- end
- //Signal a new read address command is available by user logic
- else if (start_single_read)
- begin
- axi_arvalid <= 1'b1;
- end
- //RAddress accepted by interconnect/slave (issue of M_AXI_ARREADY by slave)
- else if (M_AXI_ARREADY && axi_arvalid)
- begin
- axi_arvalid <= 1'b0;
- end
- // retain the previous value
- end
- //--------------------------------
- //Read Data (and Response) Channel
- //--------------------------------
-
- //The Read Data channel returns the results of the read request
- //The master will accept the read data by asserting axi_rready
- //when there is a valid read data available.
- //While not necessary per spec, it is advisable to reset READY signals in
- //case of differing reset latencies between master/slave.
-
- 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 && ~axi_rready)
- begin
- axi_rready <= 1'b1;
- end
- // deassert after one clock cycle
- else if (axi_rready)
- begin
- axi_rready <= 1'b0;
- end
- // retain the previous value
- end
-
- //Flag write errors
- assign read_resp_error = (axi_rready & M_AXI_RVALID & M_AXI_RRESP[1]);
-
-
- //--------------------------------
- //User Logic
- //--------------------------------
-
- //Address/Data Stimulus
-
- //Address/data pairs for this example. The read and write values should
- //match.
- //Modify these as desired for different address patterns.
-
- //Write Addresses
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- axi_awaddr <= 0;
- end
- // Signals a new write address/ write data is
- // available by user logic
- else if (M_AXI_AWREADY && axi_awvalid)
- begin
- axi_awaddr <= axi_awaddr + 32'h00000004;
-
- end
- end
-
- // Write data generation
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1 )
- begin
- axi_wdata <= C_M_START_DATA_VALUE;
- end
- // Signals a new write address/ write data is
- // available by user logic
- else if (M_AXI_WREADY && axi_wvalid)
- begin
- axi_wdata <= C_M_START_DATA_VALUE + write_index;
- end
- end
-
- //Read Addresses
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- axi_araddr <= 0;
- end
- // Signals a new write address/ write data is
- // available by user logic
- else if (M_AXI_ARREADY && axi_arvalid)
- begin
- axi_araddr <= axi_araddr + 32'h00000004;
- end
- end
-
-
-
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- begin
- expected_rdata <= C_M_START_DATA_VALUE;
- end
- // Signals a new write address/ write data is
- // available by user logic
- else if (M_AXI_RVALID && axi_rready)
- begin
- expected_rdata <= C_M_START_DATA_VALUE + read_index;
- end
- end
- //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_write <= 1'b0;
- write_issued <= 1'b0;
- start_single_read <= 1'b0;
- read_issued <= 1'b0;
- compare_done <= 1'b0;
- ERROR <= 1'b0;
- end
- else
- begin
- // state transition
- case (mst_exec_state)
-
- IDLE:
- // This state is responsible to initiate
- // AXI transaction when init_txn_pulse is asserted
- 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 last_write 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 && ~axi_wvalid && ~M_AXI_BVALID && ~last_write && ~start_single_write && ~write_issued)
- begin
- start_single_write <= 1'b1;
- write_issued <= 1'b1;
- end
- else if (axi_bready)
- begin
- write_issued <= 1'b0;
- end
- else
- begin
- start_single_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 last_read 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 && ~M_AXI_RVALID && ~last_read && ~start_single_read && ~read_issued)
- begin
- start_single_read <= 1'b1;
- read_issued <= 1'b1;
- end
- else if (axi_rready)
- begin
- read_issued <= 1'b0;
- end
- else
- begin
- start_single_read <= 1'b0; //Negate to generate a pulse
- end
- end
-
- INIT_COMPARE:
- begin
- // 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.
- 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
-
- //Terminal write count
-
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- last_write <= 1'b0;
-
- //The last write should be associated with a write address ready response
- else if ((write_index == C_M_TRANSACTIONS_NUM) && M_AXI_AWREADY)
- last_write <= 1'b1;
- else
- last_write <= last_write;
- 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 (last_write && M_AXI_BVALID && axi_bready)
- writes_done <= 1'b1;
- else
- writes_done <= writes_done;
- end
-
- //------------------
- //Read example
- //------------------
-
- //Terminal Read Count
-
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- last_read <= 1'b0;
-
- //The last read should be associated with a read address ready response
- else if ((read_index == C_M_TRANSACTIONS_NUM) && (M_AXI_ARREADY) )
- last_read <= 1'b1;
- else
- last_read <= last_read;
- end
-
- /*
- Check for last read completion.
-
- This logic is to qualify the last read count with the final read
- response/data.
- */
- 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 read ready response
- else if (last_read && M_AXI_RVALID && axi_rready)
- reads_done <= 1'b1;
- else
- reads_done <= reads_done;
- end
-
- //-----------------------------
- //Example design error register
- //-----------------------------
-
- //Data Comparison
- always @(posedge M_AXI_ACLK)
- begin
- if (M_AXI_ARESETN == 0 || init_txn_pulse == 1'b1)
- read_mismatch <= 1'b0;
-
- //The read data when available (on axi_rready) is compared with the expected data
- else if ((M_AXI_RVALID && axi_rready) && (M_AXI_RDATA != expected_rdata))
- read_mismatch <= 1'b1;
- else
- read_mismatch <= read_mismatch;
- end
-
- // 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)
- error_reg <= 1'b0;
-
- //Capture any error types
- else if (read_mismatch || write_resp_error || read_resp_error)
- error_reg <= 1'b1;
- else
- error_reg <= error_reg;
- end
- // Add user logic here
-
- // User logic ends
-
- endmodule
axi_lite_master代码测试结果:
