FPGA_HP:AXI4的学习与使用1——基础知识积累


引言

本部分解决Zynq里的一个麻烦点——AXI4协议。在AMBA的发展史上,其诞生于AMBA4,由AXI3发展而来。AXI3一般在PS端内部的外设间通信常见,而AXI4在PL端自己设计的模块间通信很常见,而PL与PS的通信,常常使用AXI4(后续只针对AXI4),若PS的接口只支持AXI3,也有专用的协议转换接口,很方便。

本技术文,仅记录学习中的一些笔记和心得,尽量做到将AXI4的东西覆盖掉,但一些很常见的,全网都有的,也不会过多去复述。


基本概念

AXI4分为三种:AXI_Lite、AXI_Full和AXI_Stream,AXI_Full有时也直接简称为AXI4或AXI了。PS与PL间的接口,如GP、HP和ACP都只支持AXI_Lite和AXI_Full协议,并不支持AXI_Stream协议,需要进行协议转换后,才能进行相应的对接。

总线:一组传输通道,是各种逻辑器件构成的传输数据通道,一般由“数据线”、“地址线”和“控制线”等构成,具体到代码就是不同的信号。

接口:一种连接标准,又被称为物理接口,Zynq上的GP、HP和ACP就是接口。

协议:传输数据的规则,这些规则将体现到代码的设计上。

GP接口:通用AXI接口,包括两个32位主设备接口、两个32位从设备接口,使用该接口,可以访问PS中的片内外设。

HP接口:高性能/带宽接口,PL端为Master,主要用于PL访问PS的存储器(DDR或On-Chip RAM),这个访问包括了PL端对存储器的“读或写”。

ACP接口:加速器一致性接口,用来管理DMA之类的,不带缓存的AXI外设,PS端是Slave,可以用来解决Cache的“缓存一致性”问题。


AXI Interconnect

这个IP的作用是提供将“一个或多个”AXI主设备连接到“一个或多个”AXI从设备的一种交换机制,通常我们Add了AXI的IP并进行自动连线后,都会自动加上这个IP,这个IP有详细一个文档去介绍,可以查阅PG059。

应用场景:IF有多个主机和从机时,可以使用AXI Interconnect将它们联系并管理起来。使用该IP可以对不同的主机ID进行处理,让可能发出相同的ID变得唯一。

为了更加深入学习该IP,此处做一个实验,该实验借鉴知乎某文,在参考文献中已标明,万分感谢!

工程说明:搭建一个BD,来简单的测试下Interconnect这IP的功能,用到的总线是AXI_Lite,使用Vivado自带的平台进行仿真测试。

01、整体的Block Design文件。
在这里插入图片描述
02、各个模块的说明。
clk_wiz_0:MMCM,模式时钟管理器,这里作用主要是产生100MHz的clk_out1和200MHz的clk_out2,类似锁相环,尝试多个时钟这样。
proc_sys_reset_x: 系统复位模块,根据输入时钟和输入的信号产生对应的高复位有效信号和低复位有效信号,为什么有这个模块呢?主要是复位信号axi_aresetn不能直接连外部的复位信号,需要使用mmcm_lock信号过proc_sys_reset做同步处理。
axi_interconnect_0: AXI Interconnect,这里管理着2个Slave接口和1个Master接口;对总线传输进行仲裁,通信,时序转换等操作。
axi_bram_ctrl_0: Bram Controller,AXI接口的Bram控制器;
blk_mem_gen_0: Block Ram资源。

03、由于Block Design可以实现自动连线,自动设置位宽等信息,所以设置内容没有AXI Interconnect RTL多,后者专用于Verilog代码中使用。

04、其实Block Design中大部分模块都是为了给Master和Slave提供工作的条件(时钟、复位)而已,真正AXI时序相关的,得看TestBeach中是如何输入的。

`timescale 1ns / 1ps
module axi_lite_test;

reg clk_100MHz, rst;
wire clk_out1, clk_out2;

reg [31:0] s00_axil_araddr, s00_axil_awaddr;
wire [31:0] s00_axil_rdata;
reg  [31:0] s00_axil_wdata;
wire [3:0] s00_axil_wstrb;
wire [2:0] s00_axil_arprot, s00_axil_awprot;
wire s00_axil_arready, s00_axil_awready, s00_axil_bvalid, s00_axil_rvalid, s00_axil_wready;
reg  s00_axil_arvalid, s00_axil_awvalid, s00_axil_bready, s00_axil_rready, s00_axil_wvalid;
wire [1:0] s00_axil_bresp, s00_axil_rresp;

reg [31:0] s01_axil_araddr, s01_axil_awaddr;
wire [31:0] s01_axil_rdata;
reg  [31:0] s01_axil_wdata;
wire [3:0] s01_axil_wstrb;
wire [2:0] s01_axil_arprot, s01_axil_awprot;
wire s01_axil_arready, s01_axil_awready, s01_axil_bvalid, s01_axil_rvalid, s01_axil_wready;
reg  s01_axil_arvalid, s01_axil_awvalid, s01_axil_bready, s01_axil_rready, s01_axil_wvalid;
wire [1:0] s01_axil_bresp, s01_axil_rresp;

reg start;

assign {s00_axil_arprot, s00_axil_awprot} = 0;
assign s00_axil_wstrb = 4'hf;
assign {s01_axil_arprot, s01_axil_awprot} = 0;
assign s01_axil_wstrb = 4'hf;

initial begin 
	clk_100MHz = 0;
	rst = 1;
	s00_axil_araddr = 0;
	s00_axil_awaddr = 0;
	s00_axil_wdata = $random;
	s00_axil_arvalid = 0;
	s00_axil_awvalid = 1;
	s00_axil_bready = 1;
	s00_axil_rready = 0;
	s00_axil_wvalid = 0;

	s01_axil_araddr = 32'd1024;
	s01_axil_awaddr = 0;
	s01_axil_wdata = 0;
	s01_axil_arvalid = 0;
	s01_axil_awvalid = 0;
	s01_axil_bready = 0;
	s01_axil_rready = 0;
	s01_axil_wvalid = 0;
    
    start = 0;
	#100
	rst = 0;
end

always #5 clk_100MHz = ~clk_100MHz;

always @ (posedge clk_out1) begin	
	if (s00_axil_wready & s00_axil_wvalid)
	   s00_axil_awaddr <= (s00_axil_awaddr < 32'd1023) ? s00_axil_awaddr + 32'd4 : 0;

	if (s00_axil_wready & ~s00_axil_wvalid) begin 
		s00_axil_wvalid <= 1'b1;
		s00_axil_wdata <= $random;
	end
	else
		s00_axil_wvalid <= 1'b0;
end

always @ (posedge clk_out2) begin 
    s01_axil_arvalid <= 1'b1;
    if (s01_axil_rvalid & s01_axil_rready)
      s01_axil_araddr <= (s01_axil_araddr < 32'd1023) ? s01_axil_araddr + 32'd4 : 0;

	if (s01_axil_rvalid & ~s01_axil_rready) begin 
		s01_axil_rready <= 1'b1;
	end
	else
		s01_axil_rready <= 1'b0;
end


design_1 d1_inst
(
.clk_100MHz		(clk_100MHz),
.clk_out1		(clk_out1),
.clk_out2		(clk_out2),
.reset_rtl_0(rst),
.s00_axil_araddr(s00_axil_araddr),
.s00_axil_arprot(s00_axil_arprot),
.s00_axil_arready(s00_axil_arready),
.s00_axil_arvalid(s00_axil_arvalid),
.s00_axil_awaddr(s00_axil_awaddr),
.s00_axil_awprot(s00_axil_awprot),
.s00_axil_awready(s00_axil_awready),
.s00_axil_awvalid(s00_axil_awvalid),
.s00_axil_bready(s00_axil_bready),
.s00_axil_bresp(s00_axil_bresp),
.s00_axil_bvalid(s00_axil_bvalid),
.s00_axil_rdata(s00_axil_rdata),
.s00_axil_rready(s00_axil_rready),
.s00_axil_rresp(s00_axil_rresp),
.s00_axil_rvalid(s00_axil_rvalid),
.s00_axil_wdata(s00_axil_wdata),
.s00_axil_wready(s00_axil_wready),
.s00_axil_wstrb(s00_axil_wstrb),
.s00_axil_wvalid(s00_axil_wvalid),
.s01_axil_araddr(s01_axil_araddr),
.s01_axil_arprot(s01_axil_arprot),
.s01_axil_arready(s01_axil_arready),
.s01_axil_arvalid(s01_axil_arvalid),
.s01_axil_awaddr(s01_axil_awaddr),
.s01_axil_awprot(s01_axil_awprot),
.s01_axil_awready(s01_axil_awready),
.s01_axil_awvalid(s01_axil_awvalid),
.s01_axil_bready(s01_axil_bready),
.s01_axil_bresp(s01_axil_bresp),
.s01_axil_bvalid(s01_axil_bvalid),
.s01_axil_rdata(s01_axil_rdata),
.s01_axil_rready(s01_axil_rready),
.s01_axil_rresp(s01_axil_rresp),
.s01_axil_rvalid(s01_axil_rvalid),
.s01_axil_wdata(s01_axil_wdata),
.s01_axil_wready(s01_axil_wready),
.s01_axil_wstrb(s01_axil_wstrb),
.s01_axil_wvalid(s01_axil_wvalid)
);
endmodule

100MHz频率下,s00_axil_awaddr 在写入数据完成(s00_axil_wready & s00_axil_wvalid)后,地址会加4,地址写到1024后会重新归零。可以看到,等到s00_axil_wready拉高,Master会把s00_axil_wvalid拉高,并生成一个随机数写入BRAM;然后s00_axil_wvalid拉低。

200MHz频率下,s01_axil_araddr在读取数据完成后(s01_axil_rvalid & s01_axil_rready),会加4。同样,地址写到1024后会重新归零。可以看到,等到s01_axil_rvalid拉高,s01_axil_rready会拉高,读取出对应数据,然后拉低s01_axil_rready。
在这里插入图片描述


握手协议

AXI4利用READY、VALID信号,设计的握手通信机制。简言之,在主从双方数据通信前,有一个握手的过程。

基本内容:数据的传输源会产生“VALID”信号,来指明何时数据有效或控制信息有效。而在目标源一方,会产生“READY”信号,来指明已经准备好接受数据或控制信息。当“VALID”信号和“READY”信号同时为高时,就会发生数据传输。根据两个信号变高的时间不同,会出现三种传输的情况。

第一种情况:VALID先变高,READY后变高。
在这里插入图片描述
第二种情况:READY先变高,VALID后变高。
在这里插入图片描述
第三种情况:READY和VALID信号同时变高。
在这里插入图片描述
虽然AXI4的握手协议有上述三种可能,但实际中,“写数据或地址信道”只有“先拉高VAILID,后等待READY”这种情况能工作,其他情况一般通过不了。所以,平时按照第一种情况来进行开发设计就OK了。


突发式读写

突发,可以理解为一次发送或接受多个数据。
下面这图是写时序的信道经典时序图,要牢牢记在脑里。写时序包括三个信道完成,写地址、写数据和写响应,从Xilinx提供的信号标准命名也可以看出,AW是Address Write,W是Write,BRESP是Response。首先,写地址信道发送一个基地址数据后,写数据信道就可以开始突发地写数据到通道中,当发送完最后一个地址数据后,WLAST信号变为高。当设备接收完数据之后,将发送一个写响应回主机,来表示写事务完成。
在这里插入图片描述
读时序的信道时序图和写类似,只不过少了写响应信道,相对更为简单。
在这里插入图片描述


其他

后续有其他关于AXI概念相关的东西,都会补充在这个贴子里。

  • 2021年01月21日____引言、基本概念、AXI Interconnect、握手协议、突发式读写
  • 7
    点赞
  • 40
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 2
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

学不懂啊阿田

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值