软件环境:vivado 2017.4 硬件平台:XC7Z020
ZYNQ片内分PS端PL端,但既然都在片内,肯定不是两个独立的个体,两部分之间联系,主要是通过AXI4总线。是总线必然有总线时序问题,这次主要通过自建模块回环仿真,来看各个通道时序关系。
自建AXI总线核,选择AXI4总线。
可以看到,总线一口有三种接口形式,分别是AXI4_LITE、AXI4_FULL、AXI4_STREAM。
AXI4-Lite:是一个轻量级的地址映射单次传输接口,占用很少的逻辑单元。
AXI4-Full:主要面向高性能地址映射通信的需求,是面向地址映射的接口。
AXI4-Stream:面向高速流数据传输,去掉了地址项,允许无限制的数据突发传输规模。
各种总线类型下面,都分master和slave两种模式。
分别以AXI_FULL接口,建立AXI_FULL_MASTER和AXI_FULL_SLAVE两个模块。展开以后看到,信号线多的一批。
其实呢,多归多,总的来说,这些信号可以划给五个通道,分别是写地址WADDR、写数据WDATA、写响应BRESP、读地址RADDR、读数据RDATA。下面具体介绍一下各个通道信号线的意义。
写地址通道WADDR
信号名 | 源 | 描述 |
AWID | 主机 | 写地址ID,用来标志一组写信号 |
AWADDR | 主机 | 写地址,给出一次写突发传输的写地址 |
AWLEN | 主机 | 突发长度,给出突发传输的次数 |
AWSIZE | 主机 | 突发大小,给出每次突发传输的字节数 |
AWBURST | 主机 | 突发类型 |
AWLOCK | 主机 | 总线锁信号,可提供操作的原子性 |
AWCACHE | 主机 | 内存类型,表明一次传输是怎样通过系统的 |
AWPROT | 主机 | 保护类型,表明一次传输的特权级及安全等级 |
AWQOS | 主机 | 质量服务QoS |
AWREGION | 主机 | 区域标志,能实现单一物理接口对应的多个逻辑接口 |
AWUSER | 主机 | 用户自定义信号 |
AWVALID | 主机 | 有效信号,表明此通道的地址控制信号有效 |
AWREADY | 从机 | 表明“从”可以接收地址和对应的控制信号 |
写数据通道WDATA
信号名 | 源 | 描述 |
WID | 主机 | 一次写传输的ID tag |
WDATA | 主机 | 写数据 |
WSTRB | 主机 | 写数据有效的字节线,用来表明哪8bits数据是有效的 |
WLAST | 主机 | 表明此次传输是最后一个突发传输 |
WUSER | 主机 | 用户自定义信号 |
WVALID | 主机 | 写有效,表明此次写有效 |
WREADY | 从机 | 表明从机可以接收写数据 |
写响应通道BRESP
信号名 | 源 | 描述 |
BID | 从机 | 写响应ID tag |
BRESP | 从机 | 写响应,表明写传输的状态 |
BUSER | 从机 | 用户自定义 |
BVALID | 从机 | 写响应有效 |
BREADY | 主机 | 表明主机能够接收写响应 |
读地址通道RADDR
信号名 | 源 | 描述 |
ARID | 主机 | 读地址ID,用来标志一组写信号 |
ARADDR | 主机 | 读地址,给出一次写突发传输的读地址 |
ARLEN | 主机 | 突发长度,给出突发传输的次数 |
ARSIZE | 主机 | 突发大小,给出每次突发传输的字节数 |
ARBURST | 主机 | 突发类型 |
ARLOCK | 主机 | 总线锁信号,可提供操作的原子性 |
ARCACHE | 主机 | 内存类型,表明一次传输是怎样通过系统的 |
ARPROT | 主机 | 保护类型,表明一次传输的特权级及安全等级 |
ARQOS | 主机 | 质量服务QoS |
ARREGION | 主机 | 区域标志,能实现单一物理接口对应的多个逻辑接口 |
ARUSER | 主机 | 用户自定义信号 |
ARVALID | 主机 | 有效信号,表明此通道的地址控制信号有效 |
ARREADY | 从机 | 表明“从”可以接收地址和对应的控制信号 |
读数据通道RDATA
信号名 | 源 | 描述 |
RID | 从机 | 读ID tag |
RDATA | 从机 | 读数据 |
RRESP | 从机 | 读响应,表明读传输的状态 |
RLAST | 从机 | 表明读突发的最后一次传输 |
RUSER | 从机 | 用户自定义 |
RVALID | 从机 | 表明此通道信号有效 |
RREADY | 主机 | 表明主机能够接收读数据和响应信息 |
说完了接口,再说一下读写的时序。写通道的时序如下所示。
master先往slave写地址,然后写数据,等数据写完后,slave会发送写响应给master。具体时序关系如下所示,首先master发送地址ADDR时,将VALID一同拉高,slave将READY也置高,也就是VALID & READY=1的时候,写入地址有效,而后开始发送数据,同样的,在发送数据时将VALID一同拉高,SLAVE把READY也拉高时,数据写入有效,当写入最后一个数据时,LAST拉一个脉冲出来,让slave知道数据写入结束,然后slave将BVALID拉一个脉冲出来,发出写响应,表示slave知道了,整个写入过程结束。
相比写操作,读操作要简单的多。读通道时序如下所示。
master先写入要读取数据的地址,然后然后依次从RDATA数据口读数就成,具体的时序关系如下图所示。首先发送要读取数据的地址给slave,时序关系同写入时相同,然后将READY口拉高,等到RDATA口有数据,当VALID拉高时候,此时表示RDATA口的数据有效,这时读取就成,当读到LAST信号时候,表示读到最后一个数据,整个读取过程结束。
回vivado将之前建立的模型连接成如下形式,不用管代码不代码的,在建立IP核的时候,不论是master还是slave其实都自带有核的例子。
添加仿真文件内容如下。
module AXI_FULL_SIM();
reg axi_ACLK; // AXI 总线时钟
reg axi_ARESETn; // 系统复位信号,低电平有效
reg r_in_key; // 模拟按键,正脉冲
wire w_err; // 状态指示,异常
AXI4_FULL_BUS_wrapper Ut1
(.ARESETN_0(axi_ARESETn),
.clk_100MHz(axi_ACLK),
.m00_axi_error_0(w_err),
.m00_axi_init_axi_txn_0(r_in_key));
parameter PERIOD = 2;
always begin
#(PERIOD/2);
axi_ACLK = ~axi_ACLK;
end
initial
begin
axi_ACLK = 1'b0;
axi_ARESETn = 1'b1;
r_in_key = 1'b0;
#(10*PERIOD);
axi_ARESETn = 1'b0;
#(2*PERIOD);
axi_ARESETn = 1'b1;
#(4*PERIOD);
r_in_key = 1'b1;
#(2*PERIOD);
r_in_key = 1'b0;
end
endmodule
运行后即可看到仿真结果如图所示。
可以看到,如果使用两个系统自动生成的AXI4的IP核直连,不加以任何修改,然后再直接仿真,默认的通信流程是先写后读。 每次突发写16次,每次32bit也就是4个字节,总共写4K个,地址从4000_0000~4000_1000。具体展开看一下读写通道。
先看写通道的。可以看到AWVALID和AWREADY同为1时写地址有效,地址写入,而后开始写数据,写数据同样在WVALID和WREADY同为1时有效,地址从4000_01c0~4000_0200~4000_0240每次递增0x40,数据从0x71~0x81每次递增0x10,每次写到最后一个数据时候WLAST一个脉冲,紧跟着响应位的BVALID和BREADY信号就来了,跟原理介绍时图上的基本一致。
再看读通道的,与写通道规律基本一致,前后两次地址线变化4000_0d40~4000_0d80~4000_0dc0间隔依旧0x40,数据这里虽然没展开,但是可以看出,两次RLAST信号之间16个RVALID,每次32bit,4个字节,位宽是固定的,每次在RVALID和RREADY同为高时,数据被读出,当读到每次的最后一个数据时,RLAST一个脉冲。
程序就不分析了吧,其实行数一般多,主要是我懒。。。不过只要知道时序关系,不论是改写还是重写,创建时自动填充的代码段,都有很好的参考意义,想看的话,在对应模块上右键。