AXI-Lite
- 数字设计
- 2025-11-17
- 73热度
- 0评论
学习一下Vivado的AXI-Lite Slave端代码。通过Vivado创建新的IP并且选择添加AXI Wrapper就会看到Vivado提供的AXI-Lite代码,下面逐项分析这段示例代码。
AW通道
AWREADY生成逻辑如下
always@(posedge S_AXI_ACLK)begin
if(S_AXI_ACLK == 1'b0)begin
axi_awready <= 1'b0;
aw_en <= 1'b1;
end
else begin
if(!axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)begin
axi_awready <= 1'b1;
aw_en <= 1'b0;
end
else if(S_AXI_BREADY && axi_bvalid)begin
axi_awready <= 1'b0;
aw_en <= 1'b1;
end
else begin
axi_awready <= 1'b0;
end
end
结合写地址和写数据通道的握手依赖关系图进行分析

AWREADY是不依赖于其他信号的,这段代码的注释中声明This design expects no outstanding transactions,这意味着slave需要写地址和写数据通道都有效的时候才认为是master发起了一次有效的传输,并且正常情况下AWREADY是一个脉冲信号。当B通道的握手也完成的时候,AWREADY变为无效。总结一下就是AWREADY会在写传输开始时,也就是AW和W通道的数据都有效时,被使能;在写传输完成,也就是R通道握手完成时,变为无效。同样的道理也可以解释下面AWADDR的代码
always@(posedge S_AXI_CLK)begin
if(S_AXI_ARESETN == 1'b0)
axi_awaddr <= 0;
else begin
if( !axi_awready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
axi_awaddr <= S_AXI_AWADDR;
end
end
W通道
W通道行为类似于AW通道,WREADY生成逻辑如下
always@(posedge S_AXI_CLK)begin
if(S_AXI_ARESETN == 1'b0)
axi_wready <= 1'b0;
else begin
if(!axi_wready && S_AXI_AWVALID && S_AXI_WVALID && aw_en)
axi_wready <= 1'b1;
else
axi_wready <= 1'b0;
end
end
下面是W通道数据写的逻辑,按照注释,只有AW通道和W通道的握手完成时才会执行写入操作,核心的控制信号逻辑如下
assign slv_reg_wren = axi_wready && S_AXI_WVALID && axi_awready && S_AXI_AWVALID;
具体写寄存器的逻辑比较简单这里不贴代码了,逻辑就是当slv_reg_wren为1时根据地址和WSTRB写入对应寄存器的字节。
B通道
B通道和W通道逻辑类似,当写入完成时slave使能BVALID并驱动BRESP,因为只有简单的寄存器读写所以BRESP都是OKAY,相应的代码如下
always@(posedge S_AXI_ACLK)begin
if( S_AXI_ARESETN == 1'b0)begin
axi_bvalid <= 1'b0;
axi_bresp <= 2'b0;
end
else begin
if(axi_awready && S_AXI_AWVALID && axi_wready && AXI_WREADY && !axi_bvalid)begin
axi_bvalid <= 1'b1;
axi_bresp <= 2'b0;
end
else begin
if(S_AXI_BREADY && axi_bvalid)
axi_bvalid <= 1'b0;
end
end
end
到这里写相关的逻辑就都有了,相应的波形图如下

AR通道
读传输只有AR和R两个通道,握手逻辑是一样的,逻辑比较简单,相关握手信号的依赖关系如下

AR通道代码如下
always@(posedge S_AXI_ACLK)begin
if(S_AXI_ARESETN == 1'b0)begin
axi_arready <= 1'b0;
axi_araddr <= 0;
end
else begin
if(!axi_arready && S_AXI_ARVALID)begin
axi_arready <= 1'b1;
axi_araddr <= S_AXI_ARADDR;
end
else
axi_arready <= 1'b0;
end
end
R通道
从依赖图可以得知RVALID依赖于ARREADY和ARVALID,相关的驱动逻辑如下
always@(posedge S_AXI_ACLK)begin
if(S_AXI_ARESETN == 1'b0)begin
axi_rvalid <= 1'b0;
axi_rresp <= 0;
end
else begin
if(axi_arready && S_AXI_ARVALID && !axi_rvalid)begin
axi_rvalid <= 1'b1;
axi_rresp <= 2'b0;
end
else if(axi_rvalid && S_AXI_RREADY)
axi_rvalid <= 1'b0;
end
end
RRDATA必须不能晚于RVALID更新,示例代码中是在AR通道握手完成后更新,核心逻辑如下
assign slv_reg_rden = axi_arready && S_AXI_ARVALID && !axi_rvalid;
这里我有点没搞清楚为什么还要求!axi_rvalid,我猜测是为了让rvalid有效期间rrdata保持不动,因为rrdata这里也有一级寄存器,如果axi_araddr发生变化的话rrdata继续采样就会出错。写传输的波形图如下

AXI-Lite的代码到这里就结束了,总的来说还是比较简单的,不过有一些东西还是值得总结学习一下的
- 协议中要求的握手以来关系肯定要实现,一个是RVALID要在ARVALID和ARREADY都使能后才允许被使能,一个是BVALID需要在AWVALID,AWREADY,WVALID,WREADY都使能后才能被使能。除此之外还有一些隐含的,例如VALID的使能不取决于对应的READY
- 想清楚一个信号什么时候该动,什么时候不该动,要做成电平还是脉冲。以aw_en为例,这个信号之所以存在,是因为需要一个信号来控制slav当前是否能接受写传输,复位之后自然是可以接受写传输,当master发起一个写传输后,在当前传输完成之前都不能接受新的写传输,所以在AW发起一次传输后,直到当前传输完成,slave都不能再接受新的传输。如何界定当前写传输是否完成?显然是R通道握手完成