【AXI总线专题】AXI-FULL-Master
【AXI总线专题】AXI-FULL-Master
- 1.axi-full概述
- 2.信号定义
- 3.测试
- 4.仿真波形
- 5.附录
- clogb2函数
- axi4中的一些参数解释
- wishbone总线
 
- 6.工程文件
概述
参考文档:
《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文件示例代码:
module sim_tb_top();reg clk,rst;initial beginrst = 0;#100;@(posedge clk)rst = 1;
endalways beginclk = 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翻转一次,常规操作如下:
	// 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;elsecnt_500ms <= cnt_500ms + 1'b1;always @(posedge clk or negedge rst) beginif(!rst)led <= 1'b1;else if(cnt_500ms == 'd24_999_999)led <= ~led;end
如上所示,这里需要定义一个cnt_500ms的变量,用来计数,通过计算,我们得知,这个变量需要计数25000000次才是500ms,那么这个变量在定义的时候就要确定它的位宽,也就是上面计算的[24:0],就是25bit。通常都是要借助程序员计算器来计算这个位宽值。
 现在有了这个函数就可以直接使用这个函数来计算了
 示例如下:
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:这个是需要传输的数据,这个数据在定义的时候是需要定义位宽的,比如
output  wire [M_AXI_DATA_WIDTH-1 : 0] 	    M_AXI_WDATA			,
wishbone总线
参考链接:CPU设计实战-Wishbone总线接口
为什么有个逻辑工程中会使用到axi_to_wishbone?我们分析一下下面这个模块,就是将axi总线转换成wishbone总线,目的就是为了简化接口的操作,因为axi总线的接口比较多。
module axi_to_wishbone(input                   aclk,         input                   aresetn,//wishbone signalsoutput 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  );
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主机读。); 
