【AXI总线专题】AXI-FULL-Master

【AXI总线专题】AXI-FULL-Master

概述
参考文档:
《3-2-03米联客2022版AXI4总线专题-20211123.pdf》
《IHI0022E_amba_axi_and_ace_protocol_spec.pdf》

1.axi-full概述

和axi-lite差不多,基本信号都差不多,就是多了几个信号。主要是因为axi-full支持突发传输,axi4支持最大256次的突发传输。

2.信号定义






3.测试

测试工程通过手动编写一个axi-full-master的模块,和slave进行通信,测试并查看仿真波形。其中的slave模式使用官方直接生产的模块。

如下图所示,一共是两个模块,一个master一个slave。我们直接把这两个模块添加到block design中,省去了例化一个个填信号的步骤。然后直接在tb文件中直接例化block design就可以了。

tb文件示例代码:

c 复制代码
module sim_tb_top();

reg clk,rst;

initial begin
    rst = 0;
    #100;
    @(posedge clk)rst = 1;
end

always begin
    clk = 0;
    #10;
    clk = 1;
    #10;
end
/*直接例化的block design,就一个时钟和一个复位信号,其他都是内部信号*/
system_wrapper system_wrapper_u0
   (
    .M_AXI_ACLK_0     (clk)  ,
    .M_AXI_ARESETN_0  (rst)
    );

endmodule

4.仿真波形

如下图所示,图中列出了写地址,写数据,写响应的时序波形。

在写地址过程中,因为是突发传输,这个过程只需要写入突发传输的起始地址,以及突发长度就行,因此这里的valid和ready信号持续的信号周期很短。

在写数据过程中,数据一直处于突发传输过程,此时的valid和ready信号需要一直保持为高电平。

last信号是和最后一个数据对齐,也就是说,在传输最后一个数据的过程中,就应该将last信号拉高,表明此时正在传输最后一个数据。

写响应阶段,是在所有数据都写入完成后,才产生valid和ready信号。

下图是读数据阶段。

程序设计的流程是先写完成后再读数据。因此在上面写响应完成后,开始一段读操作。读地址阶段的时序和写地址的时序一样。重点看下读数据阶段。

master将M_AXI_RREADY拉高后,就可以接收slave的数据了。接着slave拉高M_AXI_RVALID信号,可以看到,slave并不是一直拉高valid信号的,而是呈现脉冲式的拉高,所以接收到的数据中间都会有无效数据,就是这里的0。当然这里的0会被忽略,因为有效数据是在valid和ready同时有效的时候才正确被接收。

同样,last信号也是在接收最后一个数据的时候同时被拉高。

下图是整个程序流程的总览,即实现的写数据读数据的不断循环。整个过程读写都可以正常进行。

5.附录

clogb2函数

功能:位宽计算函数

例如,要将8个数据存到fifo中,那么fifo的深度是8,就是从0~7,这里的最大值是7,对应的就是3'b111;地址位宽就是3,这个函数就用来计算这个3。

可以应用的场景,比如在逻辑中需要点亮LED灯,每隔500ms翻转一次,常规操作如下:

c 复制代码
	// Add user logic here
	//ref_clk=50M cnt_number=25,000,000
reg [24:0] cnt_500ms;
always@(posedge clk or negedge rst)
	if(!rst)
		cnt_500ms <= 'b0;
	else if(cnt_500ms == 'd24_999_999)
		cnt_500ms <= 1'b0;
	else
		cnt_500ms <= cnt_500ms + 1'b1;

always @(posedge clk or negedge rst) begin
	if(!rst)
		led <= 1'b1;
	else if(cnt_500ms == 'd24_999_999)
		led <= ~led;
	
end

如上所示,这里需要定义一个cnt_500ms 的变量,用来计数,通过计算,我们得知,这个变量需要计数25000000 次才是500ms,那么这个变量在定义的时候就要确定它的位宽,也就是上面计算的[24:0],就是25bit。通常都是要借助程序员计算器来计算这个位宽值。

现在有了这个函数就可以直接使用这个函数来计算了

示例如下:

c 复制代码
reg [clogb2(24999999):0] cnt_500ms;

参考链接:
Verilog定义计算位宽的函数clogb2

axi4中的一些参数解释

参考链接:[axi][学习笔记]s_axi_awlen/s_axi_awsize 和s_axi_wdata关系 这个里面解释了比较容易混淆的awlen和awsize等的关系。
M_AXI_AWLEN:axi-full是突发传输的模式,一次突发传输可以传输多个数据,个数为1~256;最多传输256个数据,这个值就是用来设置一次突发传输的数据个数。
M_AXI_AWSIZE:突发传输过程中,每个传输的数据的大小(以字节为单位)。这是一个3位的信号。支持的数据的大小为1、2、4、8、16、32、64、128;那么对应关系就是
000:1
001:2
010:4
011:8
100:16
101:32
110:64
111:128

这个值和数据位宽是有关系的,数据位宽就是下面显示的M_AXI_DATA_WIDTH ;假设数据位宽是128,那么传输一个128bit的数据就是传输16个字节,也就是突发传输过程中的数据的大小是16字节,对应到M_AXI_AWSIZE 的值就是100;

使用举例:

parameter integer C_M_AXI_DATA_WIDTH = 32;

assign M_AXI_AWSIZE = clogb2((C_M_AXI_DATA_WIDTH/8)-1);//这里就是使用位宽计算公式,计算出来是010;对应上面就是4字节,也就是32位的位宽

M_AXI_WDATA:这个是需要传输的数据,这个数据在定义的时候是需要定义位宽的,比如

c 复制代码
output  wire [M_AXI_DATA_WIDTH-1 : 0] 	    M_AXI_WDATA			,

wishbone总线

参考链接:CPU设计实战-Wishbone总线接口

为什么有个逻辑工程中会使用到axi_to_wishbone?我们分析一下下面这个模块,就是将axi总线转换成wishbone总线,目的就是为了简化接口的操作,因为axi总线的接口比较多。

c 复制代码
module axi_to_wishbone(
    input                   aclk,         
    input                   aresetn,
    //wishbone signals
    output reg [31:0]		wb_addr_o,
    input       [31:0]      wb_dat_i,
    output reg	[31:0]		wb_dat_o,
    output reg			    wb_we_o,//读写使能信号,低表示读操作,高表示写操作
    output reg			    wb_stb_o,//总线选用信号,有效时代表发起一次总线操作
    output                  wb_cyc_o,//总线周期信号,代表总线正在被占用,在总线使用时须持续有效
    input                   wb_ack_i,//操作结束信号,操作结束给一个有效位
    //axi signals      
    input  [31:0]           m_axi_araddr, 
    input  [1:0]            m_axi_arburst,
    input  [3:0]            m_axi_arcache,
    input  [7:0]            m_axi_arlen,  
    input  [0:0]            m_axi_arlock, 
    input  [2:0]            m_axi_arprot, 
    input  [3:0]            m_axi_arqos,  
    output reg	            m_axi_arready,
    input  [3:0]            m_axi_arregion,
    input  [2:0]            m_axi_arsize, 
    input 		    	    m_axi_arvalid,
    input  [31:0]           m_axi_awaddr, 
    input  [1:0]            m_axi_awburst,
    input  [3:0]            m_axi_awcache,
    input  [7:0]            m_axi_awlen,  
    input  [0:0]            m_axi_awlock, 
    input  [2:0]            m_axi_awprot, 
    input  [3:0]            m_axi_awqos,  
    output reg              m_axi_awready,
    input  [3:0]            m_axi_awregion,
    input  [2:0]            m_axi_awsize, 
    input                   m_axi_awvalid,
    input                   m_axi_bready, 
    output [1:0]            m_axi_bresp,  
    output reg              m_axi_bvalid, 
    output reg [31:0]       m_axi_rdata,  
    output reg              m_axi_rlast,  
    input                   m_axi_rready, 
    output [1:0]            m_axi_rresp,  
    output reg              m_axi_rvalid, 
    input  [31:0]           m_axi_wdata,  
    input                   m_axi_wlast,  
    output reg             m_axi_wready, 
    input  [3:0]            m_axi_wstrb,  
    input                   m_axi_wvalid  
    );
c 复制代码
axi_to_wishbone host_to_wb(
    //clock and reset
    .aclk                    (sys_clk_i),
    .aresetn                 (sys_rst_n_i),
    //wishbone signals                          
    .wb_addr_o               (host_wb_addr),       
    .wb_dat_i                (host_wb_dat_o ),     
    .wb_dat_o                (host_wb_dat_i ),     
    .wb_we_o                 (host_wb_we),         
    .wb_stb_o                (host_wb_stb),        
    .wb_cyc_o                (host_wb_cyc),        
    .wb_ack_i                (host_wb_ack),        
     //AXI signals                                 
    .m_axi_araddr            (reg_m_axi_araddr  ),
    .m_axi_arburst           (reg_m_axi_arburst ),
    .m_axi_arcache           (reg_m_axi_arcache ),
    .m_axi_arlen             (reg_m_axi_arlen   ),
    .m_axi_arlock            (reg_m_axi_arlock  ),
    .m_axi_arprot            (reg_m_axi_arprot  ),
    .m_axi_arqos             (reg_m_axi_arqos   ),
    .m_axi_arready           (reg_m_axi_arready ),
    .m_axi_arregion          (reg_m_axi_arregion),
    .m_axi_arsize            (reg_m_axi_arsize  ),
    .m_axi_arvalid           (reg_m_axi_arvalid ),
    .m_axi_awaddr            (reg_m_axi_awaddr  ),
    .m_axi_awburst           (reg_m_axi_awburst ),
    .m_axi_awcache           (reg_m_axi_awcache ),
    .m_axi_awlen             (reg_m_axi_awlen   ),
    .m_axi_awlock            (reg_m_axi_awlock  ),
    .m_axi_awprot            (reg_m_axi_awprot  ),
    .m_axi_awqos             (reg_m_axi_awqos   ),
    .m_axi_awready           (reg_m_axi_awready ),
    .m_axi_awregion          (reg_m_axi_awregion),
    .m_axi_awsize            (reg_m_axi_awsize  ),
    .m_axi_awvalid           (reg_m_axi_awvalid ),
    .m_axi_bready            (reg_m_axi_bready  ),
    .m_axi_bresp             (reg_m_axi_bresp   ),
    .m_axi_bvalid            (reg_m_axi_bvalid  ),
    .m_axi_rdata             (reg_m_axi_rdata   ),
    .m_axi_rlast             (reg_m_axi_rlast   ),
    .m_axi_rready            (reg_m_axi_rready  ),
    .m_axi_rresp             (reg_m_axi_rresp   ),
    .m_axi_rvalid            (reg_m_axi_rvalid  ),//block design中的glbreg_m_axi这个slave接口的地址已经分配好了,在sdk中使用Xil_Out();函数就可以和这个slave通信了。
    .m_axi_wdata             (reg_m_axi_wdata   ),//这个从外面(block_design中)写进来的数据,即glbreg_m_axi_wdata,这个axi是从机;写进来后给axi_to_wishbone,转换到成host_wb_dat_i,从axi_to_wishbone模块输出
    .m_axi_wlast             (reg_m_axi_wlast   ),//再给wb_bus_switch;在wb_bus_switch中,根据不同的通道地址,将这个数据再转给ch1_wb_dat_o~ch5_wb_dat_o输出出去。ch1_wb_dat_o对应的是glbreg_wb_dat_i;
    .m_axi_wready            (reg_m_axi_wready  ),//glbreg_wb_dat_i这个数据再进入到global_register这个模块中,在这个模块中,将这个数据赋值给不同的寄存器,用来配置逻辑的工作模式。
    .m_axi_wstrb             (reg_m_axi_wstrb   ),
    .m_axi_wvalid            (reg_m_axi_wvalid  )//同上,wb_bus_switch中的ch1_wb_dat_i~ch5_wb_dat_i先传给host_wb_dat_o;然后这个数据再进入到axi_to_wishbone的wb_dat_i
                                                    //在axi_to_wishbone中传给m_axi_rdata,就是axi从机的输出数据接口,给axi主机读。
    ); 

6.工程文件

相关推荐
矿渣渣7 小时前
ZYNQ处理器在发热后功耗增加的原因分析及解决方案
嵌入式硬件·fpga开发·zynq
起床学FPGA11 小时前
异步FIFO的学习
学习·fpga开发
1560820721915 小时前
锁相环HMC830的调试
fpga开发
吸纹鸽17 小时前
蓝桥杯FPGA赛道积分赛
fpga开发·蓝桥杯
&Cheems17 小时前
ZYNQ笔记(二十一): VDMA HDMI 彩条显示
笔记·嵌入式硬件·fpga开发
灵风_Brend1 天前
秋招准备——2.跨时钟相关
fpga开发
希言自然也2 天前
FPGA生成随机数的方法
fpga开发
156082072192 天前
QSFP+、QSFP28、QSFP-DD接口分别实现40G、100G、200G/400G以太网接口
fpga开发·信号处理
&Cheems2 天前
ZYNQ笔记(十九):VDMA VGA 输出分辨率可调
笔记·fpga开发