AXI4 Lite协议使用笔记

Xilinx的绝大多数IP Core的寄存器读写,都是使用的AXI4 Lite协议。另外,Xilinx的Zynq系列器件,PS读写PL的寄存器也是使用的AXI4 Lite协议。以至于,AXI4 Lite的使用十分广泛。
主要的参考手册:


1.1. 信号概述

在这里插入图片描述
AXI4-Lite协议,分为5个Channel:其中写相关的有3个Channel,读有2个Channel,总计21个信号线。

注意:在Xilinx IP Core的寄存器读写接口中,信号线的数量不定,17根、18根、19根、21根的都有。其中,差异如下:

  • 19根信号线,相比于21根信号线,少ARPROT和AWPROT
  • 18根信号线,相比于19根信号线,少WSTRB

1.2. 信号详述

1.2.1. 时钟和复位

在这里插入图片描述
对于时钟信号,所有的信号在ACLK的上升沿采样。在Xilinx的应用中,AXI-Lite协议ACLK一般都是100MHz。

对于复位信号,协议的描述主要包括三点:

  • 复位低有效
  • 第二话的意思是,必须满足异步复位同步释放的要求
  • 所有的VALID信号在复位阶段都需要拉低

需要注意得是,Xilinx的IP Core对复位信号的要求不同的。如:在AXI DMA中的复位信号至少需要保持16个时钟周期,且同步到ACLK信号的时钟域。
在这里插入图片描述

1.2.2. Read address & Read data Channel

Slave端的信号,如下:

//read address channel
  .s_axi_lite_arvalid(s_axi_lite_arvalid),          // input wire s_axi_lite_arvalid
  .s_axi_lite_arready(s_axi_lite_arready),          // output wire s_axi_lite_arready
  .s_axi_lite_araddr(s_axi_lite_araddr),            // input wire [9 : 0] s_axi_lite_araddr
  .s_axi_lite_arprot(3'b0             ),            // input wire [2 : 0] s_axi_lite_arprot
//read data channel
  .s_axi_lite_rvalid(s_axi_lite_rvalid),            // output wire s_axi_lite_rvalid
  .s_axi_lite_rready(s_axi_lite_rready),            // input wire s_axi_lite_rready
  .s_axi_lite_rdata(s_axi_lite_rdata),              // output wire [31 : 0] s_axi_lite_rdata
  .s_axi_lite_rresp(s_axi_lite_rresp),              // output wire [1 : 0] s_axi_lite_rresp

注:s_axi_lite_arprot为保护类型,暂时不用,Master直接赋0即可。详见,IHI0022E-Pg73。

在这里插入图片描述
(上图中,单箭头-can,双箭头-must)
根据协议中的说明:

  • ARVALID有效,可以在ARREADY有效前(对应上图第1句)
  • ARREADY有效,可以在ARVALID有效之前,也可以在其有效之后(2,3)
  • RVALID有效,必须在ARREADY和ARVALID同时有效之后。此时,写读地址成功,之后Slave才能拉高RVALID,以指示读数据有效(4),也没必须等待BREADY有效(5)
  • RREADY有效,可以在RVALID有效之前,也可以在其有效之后(6,7)

上述存在很多情况,一般情况,满足必须得条件即可。存在多种可能的时序,满足其中一种即可。下面是Master端时序为例进行说明:
在这里插入图片描述

Step.1 Master拉高ARVALID信号,同时给ARADDR信号赋值;
Step.2 等到Slave的响应,当Slave将ARREADY拉高,即ARVALID和ARREADY信号同时有效时,读地址ARADDR写入;
Step.3 下一个上升沿时,将ARVALID拉低(写地址完成),同时ARADDR赋值为0(也可以不赋0,直到下一次写时再变化也可以),并将RREADY拉高(非此时刻必须);
Step.4 等待RVALID到来,此时,RREADY和RVALID同时有效,获取有效的RDATA和RRESP;
Step.5 判断RRESP是否为0(0代表OK),如果OK,就拉低RREADY拉低,读操作完成;

仿真实例:
以下代码,是我直接从Xilinx JESD MAC的官方例程tb中截取出来的。与我上述描述的步骤完全一致,可以借用到在自己的仿真工程中,如下:

  // AXI-Lite Read task
  task axi_read;
    //input  [29:0] offset;
    output [31:0] data;
    input  [31:0] addr;
    reg     [1:0] resp;
    begin
      // shift offset to account for AXI byte addressing
      //addr = {offset, 2'b00};
      // Drive Address valid
      @(posedge s_axi_aclk);
      #1000;
      s_axi_araddr  = addr;
      s_axi_arvalid = 1;
      s_axi_rready  = 0;
      // Address Response Phase
      @(negedge s_axi_aclk);
      while (s_axi_arready == 1'b0)
          @(negedge s_axi_aclk);
      @(posedge s_axi_aclk);
      #1000;
      s_axi_araddr  = 0;
      s_axi_arvalid = 0;
      s_axi_rready  = 1;
      // Read Data Phase
      @(negedge s_axi_aclk);
      while (s_axi_rvalid == 1'b0)
          @(negedge s_axi_aclk);
      @(posedge s_axi_aclk);
      data = s_axi_rdata;
      resp = s_axi_rresp;
      if (resp != 0) $display ("Error AXI RRESP not equal 0");
      #1000;
      s_axi_rready  = 0;
    end
  endtask // axi_read

1.2.3. Write address /Write data /Write response Channel

//write address channel
  .s_axi_lite_awvalid(s_axi_lite_awvalid),          // input wire s_axi_lite_awvalid
  .s_axi_lite_awready(s_axi_lite_awready),          // output wire s_axi_lite_awready
  .s_axi_lite_awaddr(s_axi_lite_awaddr),            // input wire [9 : 0] s_axi_lite_awaddr
  .s_axi_lite_awprot(3'b0             ),            // input wire [2 : 0] s_axi_lite_awprot
//write data channel
  .s_axi_lite_wvalid(s_axi_lite_wvalid),            // input wire s_axi_lite_wvalid
  .s_axi_lite_wready(s_axi_lite_wready),            // output wire s_axi_lite_wready
  .s_axi_lite_wdata(s_axi_lite_wdata),              // input wire [31 : 0] s_axi_lite_wdata
  .s_axi_lite_wstrb(4'hF            ),              // input wire [3 : 0] s_axi_lite_wstrb
//write response channel
  .s_axi_lite_bresp(s_axi_lite_bresp),              // output wire [1 : 0] s_axi_lite_bresp
  .s_axi_lite_bvalid(s_axi_lite_bvalid),            // output wire s_axi_lite_bvalid
  .s_axi_lite_bready(s_axi_lite_bready),            // input wire s_axi_lite_bready

注:s_axi_lite_arprot为保护类型,暂时不用,Master直接赋0即可。详见,IHI0022E-Pg73。
注:s_axi_lite_wstrb为选通脉冲,类似于tkeep信号,每一位指示1Byte,读取32bit数据时,Master直接赋值4’hF。详见,IHI0022E-Pg52。
在这里插入图片描述
根据协议中的说明:

  • AWREADY信号有效,在AWVALID or WVALID有效之前,之后都可以(对应上图1,2句)
  • WREADY信号有效,在AWVALID or WVALID有效之前,之后都可以(3,4)
  • BVALID有效,必须是在AWVALID 和 WVALID均有效之后(5),也没必须等待BREADY有效(6)
  • BREADY有效,可以在BVALID有效之前,之后也可以(7,8)

注意:上述写写地址通道和写数据通道,可以理解为相互独立的。可以同时进行写操作。当两者同时生效之后,SLAVE才可以反馈是否写成功。

上述存在很多情况,一般情况,满足必须得条件即可。存在多种可能的时序,满足其中一种即可。下面是Master端时序为例进行说明:
在这里插入图片描述
Step.1 Master拉高AWVALID和WVALID信号,同时给AWADDR和ADATA信号赋值;(上述理解写写地址和写写数据时独立的,那么就可以同时进行)
Step.2 等到Slave的响应,当Slave将AWREADY和WREADY拉高,即AWVALID和AWREADY信号同时有效时,和WVALID和WREADY信号同时有效时,写地址AWADDR和WDATA写入;
Step.3 下一个上升沿时,将AWVALID和WREADY拉低(写地址和写数据完成),同时AWADDR和WDATA赋值为0(也可以不赋0,直到下一次写时再变化也可以),写入完成
Step.4 等待BVALID到来,获取有效的BRESP;
Step.5 判断BRESP是否为0(0代表OK),如果OK,就使BREADY有效一个时钟周期,读操作完成;

注:上述,读写操作中的响应RREADY和BREADY的拉高是有区别的,这里就可以体现响应READY信号可以在VALID信号的之前,也可以之后。
仿真实例:
以下代码,是我直接从Xilinx JESD MAC的官方例程tb中截取出来的。与我上述描述的步骤完全一致,可以借用到在自己的仿真工程中,如下:

  // AXI-Lite Write task
  task axi_write;
    //input [29:0] offset;
    input [31:0] data;
    input [31:0] addr;
    reg    [1:0] resp;
    begin
      // shift offset to account for AXI byte addressing
      //addr = {offset, 2'b00};
      // Drive Address & Data valid
      @(posedge s_axi_aclk);
      #1000;
      s_axi_awaddr  = addr;
      s_axi_awvalid = 1;
      s_axi_wdata   = data;
      s_axi_wvalid  = 1;
      s_axi_bready  = 0;
      // Address Response Phase
      @(negedge s_axi_aclk);
      while (s_axi_awready == 1'b0)
          @(negedge s_axi_aclk);
      @(posedge s_axi_aclk);
      #1000;
      s_axi_awaddr  = 0;
      s_axi_awvalid = 0;
      // Data Response Phase
      @(negedge s_axi_aclk);
      while (s_axi_wready == 1'b0)
          @(negedge s_axi_aclk);
      @(posedge s_axi_aclk);
      #1000;
      s_axi_wdata   = 0;
      s_axi_wvalid  = 0;
      // BRESP phase
      @(negedge s_axi_aclk);
      while (s_axi_bvalid == 1'b0)
          @(negedge s_axi_aclk);
      @(posedge s_axi_aclk);
      resp = s_axi_bresp;
      if (resp != 0) $display ("Error AXI BRESP not equal 0");
      #1000;
      s_axi_bready = 1;
      @(posedge s_axi_aclk);
      #1000;
      s_axi_bready = 0;
    end
  endtask // axi_write

上述代码虽然是从Xilinx官方JESD MAC示例中截取出来的,实际上,这段代码是有问题的。我在进行JESD仿真时,是没有问题的。但在仿真AXI DMA实例时,就出现了问题。
在写AXI DMA的AXI4 Lite接口时出现了问题,仿真一直卡在了while (s_axi_wready == 1'b0)这里。原因如下:
JESD MAC IP Core写数据时响应的时序如下:
在这里插入图片描述
而AXI DMA写数据时,时序如下:
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-1uGj5kDP-1587309192113)(_v_images/20200419230811232_6030.png)]
可以看出:在AXI DMA这个IP CORE中,AWREADY和WREADY信号是同时来的,而JESD MAC的这两个信号不是同时来的。
而上述代码的TASK中判断这两个信号是有先后顺序的,就不支持两个信号同时来的情况。
对代码进行如下修改,让两个条件支持同时判断。
注:看来代码还是不能直接随便借用。233333

  // AXI-Lite Write task
  task axi_write;
    //input [29:0] offset;
    input [31:0] data;
    input [31:0] addr;
    reg    [1:0] resp;
    begin
      // shift offset to account for AXI byte addressing
      //addr = {offset, 2'b00};
      // Drive Address & Data valid
      @(posedge s_axi_aclk);
      #1000;
      s_axi_awaddr  = addr;
      s_axi_awvalid = 1;
      s_axi_wdata   = data;
      s_axi_wvalid  = 1;
      s_axi_bready  = 0;
      fork
          begin
              // Address Response Phase
              @(negedge s_axi_aclk);
              while (s_axi_awready == 1'b0)
                  @(negedge s_axi_aclk);
              @(posedge s_axi_aclk);
              #1000;
              s_axi_awaddr  = 0;
              s_axi_awvalid = 0;
          end
          begin
              // Data Response Phase
              @(negedge s_axi_aclk);
              while (s_axi_wready == 1'b0)
                  @(negedge s_axi_aclk);
              @(posedge s_axi_aclk);
              #1000;
              s_axi_wdata   = 0;
              s_axi_wvalid  = 0;
          end
      join
      // BRESP phase
      @(negedge s_axi_aclk);
      while (s_axi_bvalid == 1'b0)
          @(negedge s_axi_aclk);
      @(posedge s_axi_aclk);
      resp = s_axi_bresp;
      if (resp != 0) $display ("Error AXI BRESP not equal 0");
      #1000;
      s_axi_bready = 1;
      @(posedge s_axi_aclk);
      #1000;
      s_axi_bready = 0;
    end
  endtask // axi_write
  • 0
    点赞
  • 14
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值