> 技术文档 > 手把手教你verilog实现AXI总线协议读写/FPGA实现DMA数据传输/FPGA实现AMBA协议/FPGA手搓AXI协议/AXI协议详解(一)----读写模块设计_axi verilog

手把手教你verilog实现AXI总线协议读写/FPGA实现DMA数据传输/FPGA实现AMBA协议/FPGA手搓AXI协议/AXI协议详解(一)----读写模块设计_axi verilog

因最近好多伙伴问我AXI总线的实现方式,今天抽出时间给大家总结一下,并提供AXI读写的调用模块,兼容各种AXI相关设计

制作不易,记得三连哦,给我动力,持续更新!!!

完整工程文件下载:AXI读写模块源码 (点击蓝色字体获取)


1. 引言

  • 简要介绍AXI协议在AMBA协议中的位置和重要性。AMBA协议(Advanced Microcontroller Bus Architecture)是ARM公司开发的总线标准,而AXI(Advanced eXtensible Interface)是其中最广泛使用的一种,用于高性能互联。
  • 说明AXI协议的应用场景,比如FPGA中的IP核间通信、数据流传输等。
  • 提到文章的目标:通过Verilog实现AXI协议读写操作,帮助读者理解FPGA上的AXI设计。

 2. AXI协议概述

AXI的五个通道

  1. 地址通道:用于传输读请求的地址。
  2. 读数据通道:返回所请求的数据。
  3. 写地址通道:用于传输写请求的地址。
  4. 写数据通道:传输要写入的数据。
  5. 写响应通道:确认写操作是否成功。

3. verilog代码实现

3.1写数据设计

        写数据设计模块,主要包括写地址、写数据、写响应三部分组成,实现起来应该按照这个三个的顺序依次实现。

3.1.1 写地址通道 (Write Address Channel)

  • 功能:用于传输写操作的目标地址。
  • 关键信号
    • AWADDR:写操作的目标地址。
    • AWVALID:当地址有效时,主设备(Master)驱动此信号为高。
    • AWREADY:当从设备(Slave)准备好接收地址时,此信号由从设备拉高。
    • AWSIZE:突发传输中的字节数。
    • AWBURST:突发传输类型。
    • AWLEN:突发传输长度。
  • 工作流程: 主设备发出AWADDR(写地址),同时将AWVALID置高以表示地址有效,等待从设备将AWREADY置高以确认接收。地址确认后,AWVALID可以被拉低。

3.1.2 写数据通道 (Write Data Channel)

  • 功能:传输要写入的数据。
  • 关键信号
    • WDATA:要写入的实际数据。
    • WSTRB:写数据的字节选通信号,指示哪些字节是有效的。
    • WLAST:指示突发传输中最后一个数据拍。
    • WVALID:数据有效时,主设备将此信号置高。
    • WREADY:从设备准备好接收数据时,将此信号拉高。
  • 工作流程: 主设备发出WDATA(要写入的数据)和WSTRB(字节选通),并将WVALID置高,表示数据有效。当从设备将WREADY拉高时,数据被接收。对于突发传输,主设备还需要设置WLAST信号来指示最后一拍数据。

3.1.3 写响应通道 (Write Response Channel)

  • 功能:用于从设备向主设备反馈写操作的结果,确保写操作完成。
  • 关键信号
    • BVALID:当写响应有效时,从设备将此信号拉高。
    • BREADY:主设备准备好接收写响应时,驱动此信号为高。
    • BRESP:反馈写操作的结果状态(如正常完成、错误等)。
  • 工作流程: 当从设备完成写操作后,它会通过BRESP反馈写操作的结果,并将BVALID置高。主设备收到响应后,将BREADY置高,表示写响应已被接收。从设备在BREADYBVALID同时为高时完成响应握手。

突发写时序

代码实现

写数据模块,主要采用状态机三段式进行实现,大致可以分为以下五个状态

  • 写空闲(WR_IDLE):等待触发突发信号。
  • 写地址(WR_ADDR):向从机写入写地址和突发信息。
  • 写数据(WR_DATA):数据传递状态。
  • 写完成(WR_LAST):传输最后一个数据。
  • 写停止(WR_STOP):复位各自信号。

状态转移图

状态机部分代码设计:

always @ (posedge i_clk, negedge i_rst_n) begin : W_FMS3 if (~i_rst_n) begin  w_data <= 0; w_valid <= 0; w_last <= 0; w_strb <= 0; aw_addr <= 0; aw_len <= 0; aw_size <= 0; aw_burst <= 0; aw_valid <= 0;  aw_addr_cnt <= 32\'h10000000; end else case (n_state) WR_ADDR : begin w_strb <= wstrb ; aw_size <= awsize ; aw_burst <= 2\'d1 ; aw_len <= awlen ; aw_valid <= 1 ; aw_addr <= aw_addr_cnt ; end WR_DATA : begin aw_valid <= 0; if (i_valid)  begin  if (w_ready)begin w_valid <= 1; w_data <= i_data;end  elsebegin w_data <= w_data;end  end else  begin  w_valid <= 0;  w_data <= w_data;  end end WR_LAST : begin if (i_valid)  begin  w_valid <= 1;  w_last <= 1;  w_data <= i_data;  end else  begin  w_valid <= 0;  w_data <= w_data;  end end WR_STOP : begin w_last <= 0 ; w_valid <= 0 ; end default : ; endcase end 

3.2 读数据设计

        读数据设计模块,主要包括读地址、读数据部分组成,实现起来应该按照这个两个的顺序依次实现。

3.2.1 读地址通道 (Read Address Channel)

  • 功能:用于传输读操作的目标地址,发起读请求。
  • 关键信号
    • ARADDR:读操作的目标地址。
    • ARVALID:主设备(Master)将此信号置高,表示读地址有效。
    • ARREADY:从设备(Slave)将此信号置高,表示已准备好接收读地址。
    • ARLEN:读突发长度。
    • ARSIZE:读突发传输数据字节数。
    • ARBURST:读突发类型。
  • 工作流程: 主设备在ARADDR设定好目标地址后,将ARVALID置高,表示发起读请求。只有当从设备将ARREADY置高后,表示从设备已经接收了该读请求,读地址通道的握手完成。

3.2.2 读数据通道 (Read Data Channel)

  • 功能:用于传输从设备返回的读取数据。
  • 关键信号
    • RDATA:从设备返回的读数据。
    • RRESP:表示读操作的响应状态(如正常完成、错误)。
    • RLAST:指示突发读操作中最后一个数据拍。
    • RVALID:从设备将此信号置高,表示返回的数据有效。
    • RREADY:主设备将此信号置高,表示准备好接收数据。
  • 工作流程: 当从设备准备好返回数据时,会将RVALID置高,并将数据放在RDATA线上。当主设备准备好接收数据时,将RREADY置高,完成握手。如果是突发传输,当传输最后一拍数据时,从设备将RLAST信号置高以指示突发传输结束。

突发读时序

代码实现

读数据模块,主要采用状态机三段式进行实现,大致可以分为以下五个状态

  • 读空闲(RD_IDLE):等待触发突发信号。
  • 读地址(RD_ADDR):向从机写入读地址和突发信息。
  • 读数据(RD_DATA):数据传递状态。
  • 读完成(RD_LAST):传输最后一个数据。
  • 读停止(RD_STOP):复位各自信号。

读数据状态转移图:

状态机部分代码设计:

//状态执行的操作 FSM33 always @ (posedge i_clk, negedge i_rst_n) begin : R_FMS3 if (~i_rst_n) begin ar_addr <= 0; ar_len <= 0; ar_burst <= 0; ar_size <= 0; ar_valid <= 0; o_data <= 0; o_last <= 0; o_valid <= 0; rd_addr_buff <= 32\'h0000_0000; end else case (n_state) WAIT_RD : begin ar_valid <= 0; end RD_ADDR : begin ar_valid <= 1 ; ar_addr <= rd_addr_buff ; ar_len <= arlen ; ar_burst <= 2\'d1 ; ar_size <= arsize ; end RD_DATA : begin ar_valid <= 0; if (r_valid)  begin  o_valid <= 1;  if (i_ready)o_data <= r_data;  elseo_data <= o_data;  end else  begin  o_data <= o_data;  o_valid <= 0;  end end RD_LAST : begin o_last <= 1; if (r_valid && i_ready)  begin  o_data <= r_data;  o_valid <= 1;  end else  begin  o_data <= o_data;  o_valid <= 0;  end end  RD_STOP : begin o_last <= 0; o_valid <= 0; end endcase end

4. 仿真测试

        建立一个仿真测试工程,自己模拟产生AXI数据,然后存储到存储模块,并读取存储模块的数据到AXI FIFO

然后联合modelsim进行仿真,仿真结果如下

写数据仿真图:

读数据仿真图:

至此,我们的AXI 读写就彻底验证完成了!!

下一节讲解如何在实际工程中调用并使用这两个模块!!

制作不易,记得三连哦,给我动力,持续更新!!!