最近需要用到AXI接口的模块,xilinx的IP核很多都用到了AXI总线进行数据和指令传输。如果有多个设备需要使用AXI协议对AXI接口的BRAM进行读写,总线之间该如何进行仲裁,通信?
这里我们注意到,Vivado有一个叫做AXI Interconnect (RTL)的IP核,这个IP核可以实现上述功能。
本文将简单讲解AXI Interconnect IP核的使用方法,设计到Vivado的Block Design,仿真等知识运用。
为了简化整体例子的复杂度,整个测试工程项目采用了两个措施:
最终整体的Block Design结构如下图:
图1
简单介绍一下图1中的模块功能
clk_wiz_0
: MMCM,模式时钟管理器,这里作用主要是产生100MHz的clk_out1和200MHz的clk_out2,类似锁相环;proc_sys_reset_x
: 系统复位模块,根据输入时钟和输入的信号产生对应的高复位有效信号和低复位有效信号;axi_interconnect_0
: AXI Interconnect,这里管理着2个Slave接口和1个Master接口;对总线传输进行仲裁,通信,时序转换等操作。axi_bram_ctrl_0
: Bram Controller,AXI接口的Bram控制器;blk_mem_gen_0
: Block Ram
简单介绍下Block Design的AXI Interconnect IP核使用(因为Block Design可以实现自动连线,自动设置位宽等信息,所以设置内容没有AXI Interconnect RTL多,后者专用于Verilog代码中使用)
图2
这个界面设置Slave Interface的数量,与Master 模块的数量对应;Master Interface数量,与 Slave模块的数量对应,如果想不明白可以看图6。
图3
图4
这里使能S/M_AXI端口的Register Slice和Data FIFO功能,Slice对时序收敛有一定作用,但是数据输出会延迟一个周期;Data FIFO,顾名思义,可以实现数据缓存和packet mode。
图5
勾选图2的Advanced Options后,可以进入图5界面,这里可以设置S_AXI端口的优先级,优先级值越高,越优先,平行优先级的端口会使用轮询的方式处理端口请求。
图6
整个IP核的外部端口,Sxx_AXI连接Master模块的M_AXI接口;Mxx_AXI连接Slave模块的S_AXI接口;ACLK是IP核的运行时钟,ARESETN是IP核的异步低有效复位信号。
Sxx_ACLK是对应总线的总线时钟,Sxx_ARESETN是对应总线的异步低有效复位信号。同理,Mxx_ACLK是对应总线的总线时钟,Mxx_ACLK_ARESETN是对应总线的异步低有效复位信号。
图中出现了4个时钟端口,这4个时钟端口的频率可以各不相同。曾经我很疑惑ACLK的时钟频率到底应该如何设置,找到了一个在Xilinx论坛的帖子,上面的建议是连接到任一Sxx_ACLK或者Mxx_ACLK,虽然ACLK可以随意连接到一个时钟频率信号。
图1的输入端口有S00_AXI,S01_AXI的接口,clk_100MHz的时钟输入信号,reset_rtl_0的高有效复位信号;输出有100MHz的clk_out1,200MHz的clk_out2;
然后将Block Design生成为verilog文件,供其他的verilog文件直接实例化。这里我们利用留出的clk_out1,clk_out2,s00_axi,s01_axi接口,对Bram进行简单的地址读写操作,读写时钟分别为200MHz/100MHz。
Testbench里面,除了必要的initial和时钟赋值外,主要的还是对s00_axi,s01_axi的控制。
s00_axi在100MHz时钟域下,我们单独对它进行写操作。
在设计过程中,我还发现了一个奇怪的现象,原本的设计中,握手信号想等着s00_axil_awready信号拉高之后,这边的s00_axil_awvalid再拉高。结果发现awready迟迟没有拉高,在看完参考资料1后,才知道需要Master这侧的valid先拉高,否则slave的ready信号不一定会拉高;所以s00_axil_awvalid, s01_axil_arvalid设置为1 。
100MHz频率下,s00_axil_awaddr 在写入数据完成(s00_axil_wready & s00_axil_wvalid)后,地址会加4;地址写到1024后会重新归零。
可以看到,等到s00_axil_wready拉高,Master会把s00_axil_wvalid拉高,并生成一个随机数写入BRAM;然后s00_axil_wvalid拉低。
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
200MHz频率下,s01_axil_araddr在读取数据完成后(s01_axil_rvalid & s01_axil_rready),会加4;同样,地址写到1024后会重新归零。
可以看到,等到s01_axil_rvalid拉高,s01_axil_rready会拉高,读取出对应数据,然后拉低s01_axil_rready;
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
当然,为什么两个不同的总线能够对一个BRAM进行操作,这里涉及到地址分配的问题;
图7
两个总线可以访问到同一个地址,所以自然可以对同一个BRAM进行操作;那有人可能问,假如我操作s00访问的地址超过了分配的地址范围呢,那么s00_axil_bresp会等于2'd3,告知地址错误的问题。
图8
由于设计问题,读取的地址相比写入数据落后几个时钟周期,这样可以将刚写入的数据读出来。
这个实验表明AXI Interconnect不仅是总线仲裁器,还帮助时钟域不同的AXI总线完成了时序转换。除此之外,AXI Interconnect还可以实现数据位宽转换,AXI协议转换,例如AXI4/3转AXI4-Lite,AXI4转AXI3等;增加Register Slice改善时序,增加数据fifo缓存数据;
AXI Interconnect最多支持16 MI与16 SI组合。不过,当配置只有一个SI接口时,MI接口最多可以设置到64位。
其中的仲裁采用的轮询调度算法,当然,IP核可以设置每个SI的优先级,值越高,优先级越高;
当然,这篇文章只是为了简单介绍AXI Interconnect的作用,更复杂更多的功能还有待发掘。当然,功能强大意味着复杂,比如根据参考资料2,AXI4协议中的ID信号,如果在AXI Interconnect中使用不当,可能造成仲裁器死锁。
图9
看上图,在我的示例中,ACLK与S01_ACLK同源同频,所以示意图中,s01_couples从S_AXI直通到M_AXI;而s00_couples则添加了一个AXI Clock Converter做时序转换;在m00_couples中,又使用了AXI Clock Converter将ACLK转换到M00_ACLK;
至此,简单总结下在AXI通信中使用AXI Interconnect的好处:
- 真正实现了总线通信,N Master模块与M Slave模块的通信,减少了相互间通信的复杂度
- 内部实现时钟域转换,不需要外部的过度干预
- 内部可实现FIFO等,免去了很多场景下需要FIFO,Register,位宽转换,协议转换的需求
-
控制器
+关注
关注
112文章
16064浏览量
176920 -
RTL
+关注
关注
1文章
385浏览量
59648 -
VCS
+关注
关注
0文章
78浏览量
9578 -
AXI总线
+关注
关注
0文章
66浏览量
14241 -
BRAM
+关注
关注
0文章
41浏览量
10934
发布评论请先 登录
相关推荐
评论