手撕AXI-Full总线接口,实现AXI_Full Master接口

这篇具有很好参考价值的文章主要介绍了手撕AXI-Full总线接口,实现AXI_Full Master接口。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、AXI介绍

AXI全称Advanced eXtensible Interface,属于AMBA总线中的一种,由ARM公司制定。目前主流的包括AXI3和AXI4,其中AXI4又包括AXI4_Lite、AXI4_Full以及AXI4_Stream。本文是基于Xilinx AXI4 IP实现AXI4_FULL Master控制接口。

AXI协议是基于突发传输的,意味着只需要告诉首地址以及突发大小等信息即可实现数据传输。AXI_Full包括五个独立的通道
1)读地址通道;
2)读数据通道;
3)写地址通道;
4)写数据通道;
5)写响应通道。
具体的通道信号可以参考ARM官网文档,此处不列举,重点在Verilog实现,有需要补充预备知识的提前看看。

二、Verilog实现

最终设计支持Burst_len为1、2、4、8、16、32、64、128、256的传输,在地址0处写入1-16,产生Wlast,然后又在地址0处读出1-16,接收Rlast。重点在控制每个通道的Valid和Ready信号,产生写地址AWADDR、写数据WDATA、读地址ARADDR。
1)接口信号
参考Xilinx的IP,端口信号基本不变,全部复制即可,这里就不放了。
2)时序逻辑
这部分代码主要就是控制寄存器类型的Valid和Ready信号的产生,以及Waddr、Raddr和Wdata、Wlast的产生。这里需要重点关注WLAST的产生,为了支持Burst_len长度从1~256,这里对Burst_len进行判断,最终真正的WLAST信号由组合逻辑部分选择产生。

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN || (M_AXI_AWVALID && M_AXI_AWREADY))
		r_m_axi_awvalid <= 'd0;
	else if(r_m_axi_wstart)
		r_m_axi_awvalid <= 'd1;
	else
		r_m_axi_awvalid <= r_m_axi_awvalid;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_axi_awaddr <= 'd0;
	else if(r_m_axi_wstart)
		r_m_axi_awaddr <= 'd0;
	else
		r_m_axi_awaddr <= 'd0;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN || M_AXI_WLAST)
		r_m_axi_wvalid <= 'd0;
	else if(M_AXI_AWVALID && M_AXI_AWREADY)
		r_m_axi_wvalid <= 'd1;
	else
		r_m_axi_wvalid <= r_m_axi_wvalid;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN || M_AXI_WLAST)
		r_m_axi_wdata <= 'd1;
	else if(M_AXI_WVALID && M_AXI_WREADY)
		r_m_axi_wdata <= r_m_axi_wdata + 1;
	else
		r_m_axi_wdata <= r_m_axi_wdata;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_axi_wlast <= 'd0;
	else if(C_M_AXI_BURST_LEN == 1)
		r_m_axi_wlast <= 'd0;
	else if(C_M_AXI_BURST_LEN == 2 && (M_AXI_WVALID && M_AXI_WREADY && !r_m_axi_wlast))
		r_m_axi_wlast <= M_AXI_WVALID && M_AXI_WREADY;
	else if(C_M_AXI_BURST_LEN > 2 && r_burst_cnt == C_M_AXI_BURST_LEN-2)
		r_m_axi_wlast <= 'd1;
	else
		r_m_axi_wlast <= 'd0;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN || M_AXI_WLAST)
		r_burst_cnt <= 'd0;
	else if(M_AXI_WVALID && M_AXI_WREADY)
		r_burst_cnt <= r_burst_cnt + 1;
	else
		r_m_axi_wlast <= r_burst_cnt;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN || (M_AXI_ARVALID && M_AXI_ARREADY))
		r_m_axi_arvalid <= 'd0;
	else if(r_m_axi_rstart)
		r_m_axi_arvalid <= 'd1;
	else
		r_m_axi_arvalid <= 'd0;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_axi_araddr <= 'd0;
	else if(r_m_axi_rstart)
		r_m_axi_araddr <= 'd0;
	else
		r_m_axi_araddr <= 'd0;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN || M_AXI_RLAST)
		r_m_axi_rready <= 'd0;
	else if(M_AXI_ARVALID && M_AXI_ARREADY)
		r_m_axi_rready <= 'd1;
	else
		r_m_axi_rready <= r_m_axi_rready;

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_axi_rdata <= 'd0;
	else if(M_AXI_RVALID && M_AXI_RREADY)
		r_m_axi_rdata <= M_AXI_RDATA;
	else
		r_m_axi_rdata <= r_m_axi_rdata;

3)组合逻辑
这部分就是第一部分接口信号的输出逻辑。这里的clog2b为自己写的求数据位宽的函数。注意真正写入的地址是要加上一个基地址的。

assign M_AXI_AWID    = 'd0                              ;
assign M_AXI_AWLEN   = C_M_AXI_BURST_LEN                ;
assign M_AXI_AWSIZE  = clog2b(C_M_AXI_DATA_WIDTH/8 - 1) ;
assign M_AXI_AWBURST = 2'b01                            ;
assign M_AXI_AWLOCK  = 'd0                              ;
assign M_AXI_AWCACHE = 4'b0010                          ;
assign M_AXI_AWPROT  = 'd0                              ;
assign M_AXI_AWQOS   = 'd0                              ;
assign M_AXI_AWUSER  = 'd0                              ;
assign M_AXI_AWADDR  = r_m_axi_awaddr + C_M_TARGET_SLAVE_BASE_ADDR ;
assign M_AXI_AWVALID = r_m_axi_awvalid                  ;

assign M_AXI_WSTRB  = {C_M_AXI_DATA_WIDTH/8{1'b1}}      ;
assign M_AXI_WUSER  = 'd0                               ;
assign M_AXI_WDATA  = r_m_axi_wdata                     ;
assign M_AXI_WLAST  = (C_M_AXI_BURST_LEN == 1) ? w_write_last : r_m_axi_wlast ;
assign M_AXI_WVALID = r_m_axi_wvalid                    ;

assign M_AXI_BREADY = 1'b1								;

assign M_AXI_ARID    = 'd0                              ;
assign M_AXI_ARADDR  = r_m_axi_araddr + C_M_TARGET_SLAVE_BASE_ADDR ;
assign M_AXI_ARLEN   = C_M_AXI_BURST_LEN                ;
assign M_AXI_ARSIZE  = clog2b(C_M_AXI_DATA_WIDTH/8 - 1) ;
assign M_AXI_ARBURST = 2'b01                            ;
assign M_AXI_ARLOCK  = 'd0                              ;
assign M_AXI_ARCACHE = 4'b0010                          ;
assign M_AXI_ARPROT  = 'd0                              ;
assign M_AXI_ARQOS   = 'd0                              ;
assign M_AXI_ARUSER  = 'd0                              ;
assign M_AXI_ARVALID = r_m_axi_arvalid                  ;

assign M_AXI_RREADY  = r_m_axi_rready                   ;

assign w_write_last = M_AXI_WVALID && M_AXI_WREADY		;

4)状态机
这里对写逻辑和读逻辑采用了两个FSM进行控制,产生写开始Wstart和读开始Rstart信号。写读共有7个状态。

/************************状态机*************************/
always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_write_current <= P_ST_IDLE;
	else
		r_m_write_current <= r_m_write_next;

always@(*)
	case(r_m_write_current)
		P_ST_IDLE       : r_m_write_next = P_ST_WRITE_START;
		P_ST_WRITE_START: r_m_write_next = r_m_axi_wstart ? P_ST_WRITE_TRANS : P_ST_WRITE_START;
		P_ST_WRITE_TRANS: r_m_write_next = M_AXI_WLAST ? P_ST_WRITE_END : P_ST_WRITE_TRANS;
		P_ST_WRITE_END  : r_m_write_next = (r_m_read_current == P_ST_READ_END) ? P_ST_IDLE : P_ST_WRITE_END;
		default         : r_m_write_next = P_ST_IDLE;
	endcase

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_axi_wstart <= 'd0;
	else if(r_m_write_current == P_ST_WRITE_START)
		r_m_axi_wstart <= 'd1;
	else
		r_m_axi_wstart <= 'd0;

/************************状态机*************************/
always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_read_current <= P_ST_IDLE;
	else
		r_m_read_current <= r_m_read_next;

always@(*)
	case(r_m_read_current)
		P_ST_IDLE      : r_m_read_next = (r_m_write_current == P_ST_WRITE_END) ? P_ST_READ_START : P_ST_IDLE;
		P_ST_READ_START: r_m_read_next = r_m_axi_rstart ? P_ST_READ_TRANS : P_ST_READ_START;
		P_ST_READ_TRANS: r_m_read_next = M_AXI_RLAST ? P_ST_READ_END : P_ST_READ_TRANS;
		P_ST_READ_END  : r_m_read_next = P_ST_IDLE;
		default        : r_m_read_next = P_ST_IDLE;
	endcase

always@(posedge M_AXI_ACLK)
	if(!M_AXI_ARESETN)
		r_m_axi_rstart <= 'd0;
	else if(r_m_read_current == P_ST_READ_START)
		r_m_axi_rstart <= 'd1;
	else
		r_m_axi_rstart <= 'd0;

三、仿真验证

验证采用在TOP模块里例化一个Xilinx 的AXI4_Full IP以及咱们自己写的Master接口,将咱们的信号连接到AXI4_Full IP 里的Slave口,大概如下图。
axi full代码,fpga开发,arm开发

然后对TOP编写tb仿真,tb里主要产生clk,rst即可,过于简单,这里就不放了。直接看波形。

先看与写相关的通道:可以看到在设置Burst_len为16时,满足握手要求,当AWVALID和AWREADY握手,成功写入1~16,并在最后一个数据处产生WLAST信号,成功后产生BVALID,且BRESP为Okay。
axi full代码,fpga开发,arm开发
再看与读相关的通道:当ARVALID和ARREADY握手,且RVALID和RREADY握手时,成功读出1~16,并在最后一个数据处产生RLAST信号。但这里发现1)RVALID和RREADY握手时总是会产生间断,这是由于Xilinx 的IP自身问题产生的,因为RVALID对于咱们的接口来说是输入。2)最后读出的数据多了一个,这应该也是由于Xilinx 的IP自身问题产生的。总之咱们的Master接口实现是没有问题的。
axi full代码,fpga开发,arm开发
最后验证对于其他的Burst_len都是成功的。文章来源地址https://www.toymoban.com/news/detail-805002.html

到了这里,关于手撕AXI-Full总线接口,实现AXI_Full Master接口的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • ZYNQ AXI4总线访问DDR3实现图像数据乒乓存储与显示

    目录 前言 一、添加端口 二、添加局部变量 三、例化读写FIFO 四、内部变量修改,设置一次读写进行多少次突发操作 五、写地址 六、读地址 七、状态机 1.写状态机 2.读状态机 总结 在Altera FPGA进行图像处理时,我们采用的存储芯片为SDRAM,当时参照正点原子的例程是封装SDR

    2024年02月02日
    浏览(68)
  • <AMBA总线篇> AXI总线协议介绍

    目录 01 AXI协议简介 AXI协议特性 AXI协议传输特性 02 AXI协议架构 AXI协议架构 write transaction(写传输) read tramsaction(读传输) Interface and interconnect 典型的AXI系统拓扑 03 文章总结 大家好,这里是程序员 杰克 。一名平平无奇的嵌入式软件工程师。 对于学习Xilinx FPGA(ZYNQ)而言,官方提

    2024年02月10日
    浏览(44)
  • AXI4-Full Xilinx FPGA使用理解---信号定义理解

             一、AXI4 signal dir Xilinx 中文理解 ID类 AWID M2S Masters need only output the set of ID bits that it varies (if any) to indicate re-orderable transaction threads. Single-threaded master interfaces can omit this signal. Masters do not need to output the constant portion that comprises the Master ID, as this is appended by the AXI Interco

    2024年02月22日
    浏览(51)
  • AXI总线协议

    目录 AXI协议简介 通道结构 基本传输 读burst示例 连续读burst示例  写burst示例 传输顺序 握手过程 写地址通道 写数据通道 写响应通道 读地址通道 读数据通道 通道之间的关系 通道握手信号的依赖关系 关于寻址选择 burst长度 burst大小 burst类型  地址固定的burst 地址递增的bur

    2024年02月15日
    浏览(39)
  • AXI协议详解(9)-数据总线

    本章描述了 AXI 读写数据总线上不同大小的传输,以及接口如何使用字节不变字节序来处理混合字节序传输。 它包含以下部分: 数据总线 写选通 窄传输 字节不变性 AXI协议有两条独立的数据总线,一条用于读数据,一条用于写数据。 因为这些数据总线有自己独立的握手信号

    2024年02月04日
    浏览(41)
  • AXI4总线学习心得(一)

    AXI4:(For high-performance memory-mapped requirements.)主要面向高性能地址映射通信的需求,是面向地址映射的接口,允许最大 256 轮的数据突发传输; AXI4-Lite:(For simple, low-throughput memory-mapped communication )是一个轻量级的地址映射单次传输接口,占用很少的逻辑单元。 AXI4-Stream:

    2024年02月12日
    浏览(42)
  • AMBA总线协议AXI——学习笔记

    2023.3.25 2023.4.23 AXI :高级可拓展接口 高性能、高带宽、低延迟 单向通道体系结构 独立的地址和数据通道 支持多项数据交换。通过 并行执行burst操作 ,极大地提高了数据吞吐能力。 AXI4 :高性能内存映射需求(如读写DDR、使用BRAM控制器读写BRAM等),为了区别,有时候也叫这

    2023年04月23日
    浏览(52)
  • FPGA——AXI4总线详解

    目录 AXI4总线 1、什么是AXI 2、AXI4协议的优势 AXI4的工作模式 AXI4读操作: AXI4写操作 AXI4和AXI4-Lite、AXI4-Stream接口信号 握手信号 AXI相关术语     AXI(Advanced eXtensible Interface高级可扩展总线)是一种总线协议     AXI4包含3种类型的接口: 1)AXI4:主要面向高性能地址映射通信的

    2024年02月02日
    浏览(56)
  • 【ARM AMBA AXI 入门 11 - AXI 总线 AWCACHE 和 ARCACHE 介绍】

    请阅读 【ARM AMBA AXI 总线 文章专栏导读】 转自:https:

    2024年02月09日
    浏览(52)
  • XILINX ZYNQ 7000 AXI总线 (二)

    了解了AXI 的大部分内容后,开始做一个实战,就是完成AXI 结构的输入输出搭建。 一.创建一个IP 3. 4. 5. 6.选择AXI FULL,创界主接口和从接口 7. 8.可以看到XILINX AXI FULL 的源代码 二.创建一个新的工程,把IP导入到这个工程 2.创建 block design 放入两个AXI IP 三 设计 创建两个 接口进行

    2024年02月16日
    浏览(58)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包