在用zynq开发板玩FPGA时,经常会用到AXI总线。这里对AXI总线的读写过程做一个记录,备忘。
一、AXI简介
AXI协议是基于burst的传输,并且定义了以下5个独立的传输通道:读地址通道、读数据通道、写地址通道、写数据通道、写响应通道。
地址通道携带控制消息用于描述被传输的数据属性,数据传输使用写通道来实现“主”到“从”的传输,“从”使用写响应通道来完成一次写传输;读通道用来实现数据从“从”到“主”的传输。
5个传输通道均使用VALID/READY信号对传输过程的地址、数据、控制信号进行握手。使用双向握手机制,传输仅仅发生在VALID、READY同时有效的时候。
即,所有的握手及传输机制都在下图这个接口中。即所有的操作都已经封装好了,我们在自定义IP时,只需要考虑什么时候拉高VALID,并且设备返回了READY响应,表明此刻数据已经开始传输了。
比如下面这段代码,当我自己控制的w_fdma_locked 信号拉高,我就把写数据的valid拉高,开始准备传输。
//AXI4 write data---------------------------------------------------
always @(posedge M_AXI_ACLK)
if(M_AXI_ARESETN == 1'b0)
axi_wvalid <= 1'b0;
else if(w_cycle_flag == 1'b0 && w_fdma_locked == 1'b1)
axi_wvalid <= 1'b1;//当我自己控制的w_fdma_locked 信号拉高,我就把写数据的valid拉高,开始准备传输
else if(w_cycle_flag == 1'b1 && axi_wlast == 1'b1)
axi_wvalid <= 1'b0;
然后,等待设备端的ready响应回来,vaild和ready信号都拉高了,表明已经传输了一个burst数据。
//AXI4 write data user counter for burst lenth----------------------
wire w_next = (axi_wvalid && M_AXI_WREADY);
always @(posedge M_AXI_ACLK)
if(M_AXI_ARESETN == 1'b0)
w_word_cnt <= 'd0;
else if(w_word_cnt==C_M_AXI_BURST_LEN)
w_word_cnt <= 'd0;
else if(w_next)
w_word_cnt <= w_word_cnt + 1'b1; //vaild和ready信号都拉高了,表明已经传输了一个burst数据。
else
w_word_cnt <= w_word_cnt ;