手把手教你verilog实现AXI总线协议读写/FPGA实现DMA数据传输/FPGA实现AMBA协议/FPGA手搓AXI协议/AXI协议详解(一)----读写模块设计
因最近好多伙伴问我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
else
begin
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;
else
o_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 读写就彻底验证完成了!!
下一节讲解如何在实际工程中调用并使用这两个模块!!
制作不易,记得三连哦,给我动力,持续更新!!!

浙公网安备 33010602011771号