手把手教你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的五个通道:
- 读地址通道:用于传输读请求的地址。
- 读数据通道:返回所请求的数据。
- 写地址通道:用于传输写请求的地址。
- 写数据通道:传输要写入的数据。
- 写响应通道:确认写操作是否成功。
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
置高,表示写响应已被接收。从设备在BREADY
和BVALID
同时为高时完成响应握手。
突发写时序
代码实现
写数据模块,主要采用状态机三段式进行实现,大致可以分为以下五个状态
- 写空闲(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 读写就彻底验证完成了!!
下一节讲解如何在实际工程中调用并使用这两个模块!!
制作不易,记得三连哦,给我动力,持续更新!!!