AMBA总线规范
AMBA规范由ARM公司制定,用于SoC内IP互联
AMBA即(Advanced Microcontroller Bus Architecture,AMBA)规范是一种开放式标准片上互联规范,用于连接和管理片上系统中的各个功能模块(IP)。显而易见,AMBA协议是一套片上总线协议,一般来说其信号线数量都比较多——ARM通过这套协议规定了各种信号线的作用,并没有规定信号线的位宽和具体实现,所以说每个芯片中的AMBA都可能具有不同的架构
AMBA中有以下几个主要接口:
- 高级外设总线APB:用于低速低功耗外设连接
- 高级高性能总线AHB:用于高速外设连接
- 高级可扩展接口AXI:最普遍使用的高性能总线
- 高级跟踪总线ATB:用于在芯片外围移动跟踪数据
- AXI一致性扩展接口ACE:用于移动设备的大小核之间高速连接
- 相关集线器接口CHI:用于网络和服务器设备的高带宽高性能数据传输
APB规范
在APB总线中,唯一的主机为APB总线桥,其它外设都是从机。因此APB总线不需要有一个像AHB一样的仲裁器以及其它控制器,因此通常APB总线可看做由APB总线桥和APB上的从设备两部分组成。APB总线通常是AHB或者ASB系统总线(已经过时的总线)的扩展,便于外设链接到系统总线上,AHB和APB之间就使用APB总线桥来链接
APB规定所有信号必须在时钟上升沿进行传递
APB总线包含8根信号线,都是以H开头,区别其他的AMBA总线信号:
- PCLK:总线时钟,由总线时钟源提供
- PRESETn:复位信号,低电平有效,由系统总线复位信号提供
- PADDR:总线地址信号,由外设APB总线桥提供
- PPROT:保护信号,用于表示普通的、剥夺的或安全保护级别
- PSELx:总线选择信号,该信号表示选中某个从设备,每个从设备都应该有一个PSELx信号
- PENABLE:总线数据传输使能,用于触发APB总线的访问周期
- PWRITE:总线访问方向信号,信号拉高表示APB写访问;信号拉低表示APB读访问
- PWDATA:写数据信号,使用该信号线驱动写数据总线
- PRDATA:读数据信号,在读周期时从所选择的从设备驱动该总线,宽度受限(最高32位)
- PSTRB:写选通信号,用于表示写传输时更新哪个字节通道。每8位使用一个PSTRB信号线控制。在读传输时,写选通信号不活动
- PREADY:总线准备信号,从设备控制该信号来扩展APB传输
- PSLVERR:总线错误信号,用于表示传输失败。外设可以不使用PSLVERR引脚,在外设不包含该引脚时,APB桥的数据应适当拉低
以上总线结构可以和下文相互参考理解
读写时序
无等待状态写
- 需要一个建立周期寄存PADDR、PWDATA、PWRITE、PSEL,这些信号会在PCLK上升沿完成寄存
- 在第二个周期,PENABLE和PREADY寄存,PENABLE表示传输访问周期开始;PREADY表示PCLK的下一个上升沿从设备可以完成传输
- 第三个周期完成之前,PADDR、PWDATA和控制信号会一直保持有效
- 第四个周期,PENABLE和PSEL变成无效,等待下一个传输开始
有等待状态写
- 在访问周期开始时,PENABLE为高时,可以通过拉低PREADY来扩展传输
- PREADY拉低后,可以添加两个传输周期
- 新添加的周期也可以是有等待状态的,即可以通过拉低PREADY来无限延长传输周期
无等待状态读
基本时序和无等待状态写类似,但是使用PRDATA作为信号传输线,在读传输结束之前,从设备必须主动提供数据
有等待状态读
与有等待状态写类似,可以通过拉低PREADY来实现延长传输周期
事实上,除了写信号有效性相反外,APB读操作时序和写操作时序非常相似。特别地,如果写操作之后跟随着读操作或者相反,那么需要 3个等待周期来完成读操作。通常的情况下,不会有读操作之后紧跟着写操作的发生,因为两者之间CPU会进行取指操作——更重要的是指令存储器不太可能直接挂在APB总线上
错误响应
传输中使用PSLVERR信号来指示APB总线传输的错误条件。
为了防止读写交易过程中发生错误,当PSEL、PENABLE、PREADY都为高时,PSLVERR有效
当外设接收到一个错误时,写交易并不会更新外设内的寄存器;而当读交易能够返回无效的数据,对于读错误,并不会要求外设将数据总线驱动置0
APB控制状态机
APB总线状态机如上图所示
- IDLE:空闲状态,APB总线默认处于此状态
- SETUP:建立状态,当请求传输时,PSEL=1。在一次传输中,该状态只会保留一个时钟周期
- ACCESS:访问状态,PSEL=1,PENABLE=1。要求地址信号、选择信号、读/写数据信号保持不变。准备信号PREADY决定了是否从ACCESS状态退出(PREADY=0,保持;PREADY=1,退出,如果此使没有其他传输请求,就返回IDLE,否则继续进入SETUP)
APB的每次传输均需消耗2个周期的时间
AHB规范
APB总线用于低速低功耗的情况,一般只是用他来控制外设的寄存器;而AHB总线则通常用于更高速的情况——基于ARM核的MCU一般都使用AHB连接内核和APB总线。
如上图所示,典型AMBA总线系统就是这样,ARM核、片上RAM、DTCM/ITCM等高带宽内存、DMA设备这些需要高速传输的设备挂载到AHB总线上;APB总线连接低速的定时器、GPIO、串口、片外总线控制器等外设;AHB总线和APB总线间通过总线桥相连不过近年来,随着外设和片外总线速度越来越高(MCU逐渐整合DSP功能),一些高速定时器、高速GPIO都会被直接挂载到AHB总线上
与APB总线协议不同,AHB总线具有以下特性:
- 高性能:支持流水线操作和分割交易(分割交易含义在后文给出)
- 支持猝发传输(也就是突发传输Burst Mode):在一次传输内向固定地址传输多个数据字,也就是说可以一次传输一个地址和一批地址连续的数据
- 可由多个总线主设备控制
总线互联
AHB协议规范只规定了总线的通信时序,并没有规定总线的具体实现方法和互联机制,于是可以在AHB基础上采用多路复用器互联、总线矩阵等等实现思路
最基本的互联方式就是多路复用器互联:使用两个MUX分别控制地址信号线和读写数据信号线的传输,使用一个译码器实现主设备控制读写数据和响应信号的切换,所有总线设备都由总线仲裁器控制。如下图所示
总线操作流程
总线仲裁
在开始传输前,主设备需要先向AHB总线仲裁器提出使用申请,总线仲裁器随后会根据仲裁逻辑授权主设备进行总线访问。
在总线仲裁之前,允许一个主设备以特定的猝发方式完成所有传输。但是为了避免产生过长的仲裁延迟,仲裁器可以将一个猝发分解,这个操作称为分割交易
猝发传输
在总线仲裁完毕后,主设备会启动AHB传输,在这个阶段可以使用两种被允许的猝发传输逻辑(不知道该怎么翻译比较好):
- 增量猝发:在地址边界不回卷
- 回卷猝发:在特殊的地址边界回卷
每次传输由地址和控制周期与数据周期构成
在传输期间,所有从设备必须采样地址
从设备回报
在每次传输期间,从设备使用响应信号HRESP[1:0]显示状态,可选的状态如下:
- OKAY:传输正常,当HREADY=2’b11时,表示传输成功结束
- ERROR:传输失败。表示发生传输错误
- RETRY和SPLIT:表示不能立即完成传输,但是总线主设备应该继续尝试传输
如果发生分割交易,主设备会在这个时间段向仲裁器提出仲裁以便完成猝发传输中剩余的操作
读写时序
如果没有猝发传输或等待,主设备会发起一个普通传输,分成两个主要部分
地址周期
这个环节持续一个时钟周期,在第一个HCLK上升沿,主设备会先驱动总线上的地址和控制信号并保持
数据周期
在下一个时钟上升沿,从设备采集总线上的地址和控制信号
从设备完成采集后立刻驱动响应信号线,在第三个时钟上升沿时,主设备再采样这个响应
数据周期可以持续几个时钟周期,因为在任何一个传输中,从设备都可能插入等待状态。在读传输的等待状态中,从设备不必提供有效数据,在将要完成传输前提供有效数据即可
为了允许更高性能的操作,AHB总线允许流水线操作:在前一个数据周期结尾,一旦主设备采样完成就可以启动地址周期,驱动总线的地址和控制信号,这样从设备就能够获得充足时间响应一次传输
AHB总线的信号线种类
AHB总线的信号都是以H开头,区别其他的AMBA总线信号
信号名 | 信号源 | 信号功能 |
---|---|---|
HCLK | 总线时钟源 | 总线时钟信号,上升沿有效 |
HRESET | 系统复位 | 系统reset信号,低电平有效 |
HADDR[31:0] | 主设备 | 32位系统地址总线 |
HTRANS[1:0] | 主设备 | 传输类型,一共有四种类型:NONSEQ、SEQ、IDLE、BUSY |
HSIZE[2:0] | 主设备 | 每次传输的数据大小。以字节为单位。最高支持1024位 |
HBURST[2:0] | 主设备 | 猝发传输类型,一共有8种 |
HPROT[3:0] | 主设备 | 保护控制信号 |
HWDATA[31:0] | 主设备 | 写数据信号线 |
HSELx | 译码器 | 从设备选择信号线 |
HRDATA[31:0] | 从设备 | 读数据信号线 |
HREADY | 从设备 | 传输完成信号。当这个信号线拉高时,表示当前传输完成;从设备也可以通过拉低这个信号线来延长一个传输。注意:从设备需要2个HREADY信号线,其中一个作为输出,一个作为输入 |
HRESP[1:0] | 从设备 | 从设备给主设备的响应信号。一共有四种:OKAY、ERROR、RETRY、SPLIT |
下面是仲裁器的信号 | ||
HBUSREQx | 主设备 | 主设备请求信号线。主设备通过该信号线向仲裁器发出获得总线使用权的请求信号,最多支持16个主设备 |
HLOCKx | 主设备 | 总线锁定信号线。如果一个主设备希望自己在传输期间不丢掉总线,则需要向仲裁器发送这个锁定信号 |
HGRANTx | 仲裁器 | 授权信号线。仲裁器的仲裁结果会通过该信号线传送给每一个主设备。当HREADY和HGRANTx同时为高时,主设备被允许获取系统总线 |
HMASTER[3:0] | 仲裁器 | 主设备ID信号线。仲裁器为每一个主设备分配对应的的ID,用来给多路选择器提供选择信号和为SPLIT操作提供控制信号 |
HMASTLOCK | 仲裁器 | 总线阻塞信号。表示当前的主设备正在执行锁定操作。该信号和HMASTER时序相同 |
HSPLITx[15:0] | 具有SPLIT操作的从设备 | 仲裁器SPLIT控制信号 |
传输类型编码
每个传输都有独立的传输类型,由HTRANS[1:0]表示
- 00:IDLE(空闲)。表示没有请求数据传输,这个信号表示总线主设备获得了总线控制权但是并没有执行数据传输。这种情况下从设备需要返回一个零状态等待信号OKAY并忽略本次传输
- 01:BUSY(忙碌)。忙传输,允许总线主设备在猝发传输中插入空闲周期。一般这种类型表示主设备正在连续执行猝发传输但不能立即产生下一次传输。当一个主设备触发该类型时,要求它驱动带地址和控制信号必须反映猝发中的下一次传输;从设备则应该忽略这种传输
- 10:NONSEQ(非连续)。一次猝发的第一次传输或者一个独立传输,表示地址与控制信号和前一次传输无关。总线上的单个传输会被看作一次猝发传输,随意使用这个信号会导致传输不连续
- 11:SEQ(连续)。表示在一次猝发传输中剩下的传输是连续传输且与前一次传输有关,控制信息和前一次传输时一样,地址等于前一次传输的地址加上传输大小(以字节为单位)。在回卷猝发的情况下,传输地址需要在地址边界处回卷,回卷值等于传输大小乘传输次数
1 | // Transfer type: HTRANS[1:0] |
传输控制信号
每次AHB传输中,都会使用一组控制信号线提供传输的附加信息,要求他们的时序和地址总线时序严格一致,并且信号在猝发传输中保持不变
下面是用到的控制信号线
传输方向HWRITE
HWRITE=1时,表示写传输,主设备会将数据放到写数据总线HWDATA[31:0]
HWRITE=0时,表示读传输,从设备会将数据放到读数据总线HRDATA[31:0]
1
2
3// Write signal: HWRITE
传输大小HSIZE
使用HSIZE[2:0]表示传输宽度,该信号线和HBURST[2:0]信号一起决定了回卷猝发的地址边界
有以下几种选项:
- 000:8位,字节
- 001:16位,半字
- 010:32位,字
- 011:64位,双字
- 100:128位
- 101:256位
- 110:512位
- 111:1024位
1
2
3
4
5
6
7
8
9// Transfer size: HSIZE[2:0]
保护信号HPROT[3:0]
用于提供附加信息,一般提供给能执行不同保护级别的模块使用,表示传输时一次预取指或数据访问、特权模式、用户模式访问,或带高速缓存/无高速缓存
设备在没有严格要求的情况下不需要使用该信号
- HPROT[0]:0,预取指;1,数据访问
- HPROT[1]:0,用户模式;1,特权模式
- HPROT[2]:0,无缓冲;1,带缓冲
- HPROT[3]:0,无高速缓存;1,带高速缓存
猝发操作详解
AHB协议规定了4、8、16拍的基本猝发和未定长度的猝发。协议默认支持两种猝发方式
递增猝发:访问连续地址且猝发中每次传输的地址仅是前一次地址的一个递增和回卷
回卷猝发:若传输起始地址并未和猝发中的字节总数对齐,那么传输地址会在达到边界处回卷
一个4拍回卷猝发的字访问将在16字节边界回卷,因此若传输起始地址是0x34,那么它会包括0x34、0x38、0x3C和0x30四个地址,其中0x30是由回卷导致的
通过HBURST[2:0]信号线指示促发信息,具有8种可能的猝发类型:
- 000:单一传输
- 001:未定长度的递增猝发
- 010:4拍回卷猝发
- 011:4拍递增猝发
- 100:8拍回卷猝发
- 101:8拍递增猝发
- 110:16拍回卷猝发
- 111:16拍递增猝发
1 | // Bus operation: HBURST[2:0] |
特别注意:猝发不能超过1KB的地址边界
猝发大小表示猝发的节拍数量而不是一次猝发传输的实际字节数——每拍字节数是由HSIZE[2:0]指示的
对于一个从设备而言,可以在不允许完成一个猝发的特殊情况下提前终止猝发传输。一般通过监控HTRANS信号完成,如果产生一个非连续或空闲传输,则表示新的猝发开始,需要保证在此之前终止了前一次的猝发传输,并向主设备提供过连续或忙指示
地址译码器
AHB总线上的从设备一般共用一个中央地址译码器提供选择信号HSELx
一般要求这个译码器尽可能简单可靠,避免复杂的逻辑实现高速操作
协议规定:
- 从设备只能在HREADY为高时采样地址总线信号、控制信号和HSELx信号
- 当HSELx信号为高时,表示当前传输完成,因此在特定情况下会在HREADY为低时采样HSELx信号,但会在传输完成后更改选中的从设备
- 总线主设备不能执行超过1KB地址边界的递增传输
- 在存储器映射不能完全填满存储空间时,需要设置一个额外的默认从设备来让主设备访问不存在地址空间时提供响应,要求至少实现以下两个响应
- ERROR:当传输访问不存在的地址空间或出现非连续传输时
- OKAY:当空闲或访问不存在的地址空间(默认从设备)时
从设备传输响应时序
从设备使用HREADY信号来扩展一次AHB传输的数据周期——HREADY=0,表示要扩展传输;否则表示传输完成,同时可以结合从设备输出的HRESP[1:0]信号表示传输情况
协议推荐从设备不要插入多余16个扩展传输等待状态,否则单个访问会将总线锁定较长的时钟周期,影响片上数据传输——不过这并不是强制规定
HRESP[1:0]具有以下四种状态:
- 00:OKAY,表示成功完成传输
- 01:ERROR,表示发生传输错误,出现错误条件时,需要两个周期响应
- 10:RETRY,表示传输并未完成,总线主设备应重新传输直到完成,要求两个周期响应。仲裁器收到该指示后会继续使用原有的优先级方案,重新为申请总线的设备排序并进行调度分配
- 11:SPLIT,表示未成功完成传输,下次授权总线主设备访问总线时再尝试传输;当能够完成传输时,从设备会将请求代替主设备访问总线,要求两个周期响应。仲裁器收到该指示后会调整优先级方案来让其他主机的传输优先完成,随后再进行当前主机的传输
1 | // Transfer response: HRESP[1:0] |
上面要求两个周期响应的情况被称为双周期响应,需要在最后一个传输的前一个周期驱动HRESP[1:0]表示扩展一个周期。而如果从设备还需要更多周期,应该在传输开始时将HREADY信号拉低,同时响应OKAY。双周期响应允许主设备有足够时间取消该地址,并且在下次传输前驱动HTRANS[1:0]为空闲传输
特别的,如果从设备出现错误响应,主设备可以选择取消猝发中剩下的传输,但这并不是强制规定
由于分割传输的“释放总线”特性,可以更有效地实现长数据分批传输
数据总线
AHB协议要求读写数据总线至少为32位,但是允许用户扩展数据位,一些高性能核使用64位的读写数据总线
写数据总线HWDATA
写数据总线依赖主设备驱动,如果使用扩展传输,总线主设备需要保持数据有效知道HREADY为高(表示传输完成)为止。要求传输与数据宽度相等的数据宽度对齐:字传输对其到字边界,半字传输对齐到半字边界,以此类推。
同时需要区分大端和小端序,二者的有效字节通道是正好相反的,如下图所示
显而易见,不要把端序不同的设备接到同一个总线上
读数据总线HRDATA
从设备负责驱动读数据总线,当HREADY拉低,可以扩展读传输过程,从设备只需在传输的最后一个周期提供有效数据。
对于小于总线宽度的数据传输,从设备需要在有效的字节通道提供有效数据,总线主设备负责从这些通道内选择数据采样,且只有传输以OKAY响应结束时,从设备才需要提供有效数据
端结构
AHB总线不支持动态端结构
同时对于其他具有相似性能的总线,也不推荐支持动态端结构——因为它的面积和功耗开销太大了
仲裁器
设置总线仲裁器的目的是保证任意时刻只有一个主设备在占用总线。仲裁器会检测多个主设备的总线使用需求,确定当前请求总线的主设备中优先级最高的主设备,并动态调节来自从设备的分割传输请求。
仲裁器作为总线主控设备使用以下信号线:
HBUSREQx总线请求信号:主设备会使用该信号请求访问总线
因为一个系统中最多有16个独立的总线主设备,因此x在0~15之间
HLOCKx总线同步锁定信号:用于通知仲裁器主设备正在进行不可分割的传输
一旦该信号拉高,仲裁器就不应该授权其他主设备访问总线
主设备应当保证寻址完毕之前HLOCKx信号在一个周期内有效,防止仲裁器改变授权信号
HGRANTx授权信号:由仲裁器产生,高电平有效,表示对应的主设备优先级最高,享有总线控制权,优先考虑锁定传输和分割传输。
得到该信号确认的主设备,在HCLK上升沿时HREADY为高——当HREADY和HGRANTx同时为高时,主设备被允许获取系统总线
HMASTER[3:0]主设备ID信号线:表示当前被授权使用总线的主设备编号
特别情况,具有分割传输能力的从设备也能请求主设备号,以便提示仲裁器能够完成一个分割传输的主设备
HMASTLOCK锁定信号:指示某个传输是一个锁定序列的一部分
表示当前的主设备正在执行锁定操作
HSPLIT[15:0]分割传输信号:从设备用来指示能够完成一个分割传输的总线主设备,仲裁器获取该信号线上数据来向对应的主设备提供授权完成分割传输
下面是仲裁器的一个实现
1 | /* |
这是仲裁器的总线接口
1 | /* |
上面部分统一实现了仲裁器内部的控制寄存器和输出寄存器,带next
的寄存器变量都是用于预存下个周期的数据,该部分代码相当于经典三段式状态机的第一段
实现上,仲裁器输出可以用多个mealy状态机的组合实现:在一次普通传输中,总线主设备首先通过HBUSREQx请求总线使用权,仲裁器在HCLK上升沿采样请求,随后在内部判断访问总线的下一个主设备。仲裁器通过HGRANTx信号线和HMASTER[3:0]信号线授权主设备。主设备获取授权后可以选择通过拉高HLOCKx信号锁定访问总线,仲裁器在HCLK上升沿采样该信号后会锁定总线并阻止其他设备获取总线控制权。所有操作都要发生在总线空闲也就是HRADY为高时
需要解释一下默认主设备的概念:每个系统必须包含一个默认主设备——如果其他所有主设备不能使用总线,则授权主设备使用总线且它只能执行空闲传输;如果其他主设备都在等待分割交易,则必须给默认主设备授权总线。这是为了便于降低功耗总线。下面的代码就是默认主设备的输出——默认主设备会一直保持下面的总线驱动方式
1 | assign HTRANS = |
特别地,在猝发传输时,仲裁器授权主设备获取总线没有必要继续请求总线以便完成传输,仲裁器应使用HBURST[2:0]信号决定主设备请求的传输个数,如果主设备希望在当前正在进行的传输之后执行另一个猝发,主设备需要在猝发中重新拉高HLOCKx;对于未定长度的猝发,主设备应继续请求,直到已经开始最后一次传输。猝发传输结束时,最后一个地址采样的同时仲裁器会采样新的HGRANTx数据
下面是负责控制输出的电路
1 | /* |
下面是各个信号的判断电路
总线需要监视来自各个主设备的HLOCKx信号,为了确定主设备何时希望执行一个锁定连续传输
1 | //is_degrant判断逻辑 |
下面的电路则是典型的计数器处理状态机
1 | //next_count计算和更新电路(状态机) |
下面的电路负责分割交易时的主设备掩码处理
1 | //next_req_mask和req_mask计算/更新电路 |
早期猝发停止:在一般的猝发传输结束之前,仲裁器不会把总线移交给一个新的主设备,但是如果仲裁器决定必须提前终止猝发来防止过长的总线访问时间时,他可能在一个猝发完成之前将总线授权转移给另一个总线主设备。这种情况称为早期猝发停止。主设备授权总线控制权后,它必须重新断言总线请求(包括HBURST、HTRANS信号)来完成猝发传输。
协议建议但并不规定:主设备在任何锁定连续传输之后插入一个空闲传输,以提供给仲裁器在准备另一个猝发传输之前改变总线授权的机会
分割交易详解
分割交易也称为分割传输:根据从设备的响应操作来分割主设备,这是从设备响应速度不够的无奈之举
在分割传输时,可以通过给从设备提供地址和合适的数据来提高总线的整体使用率——当且仅当从设备认为传输执行将占据大量时钟周期的情况下会使用分割传输机制。分割传输信号由从设备提供——这一点上文中已经提到过,但还是需要强调主设备并没有分割传输的命令权——仲裁器则负责监视分割传输信号并在内部屏蔽分割传输主设备的任何请求,这就是主设备掩码的作用
从设备需要通过断言合适的地址位来让仲裁器识别到哪个主设备应该使用分割传输;如果系统中具有多个从设备,它们的信号需要经过或门传输给仲裁器。协议建议将所有分割传输能力的从设备设计成支持最大十六个主设备
分割传输的执行顺序如下:
- 主设备发起总线传输
- 如果从设备发现需要很多周期才能获取到主设备需要的数据,他将发起分割传输
- 才能够设备广播一个标记表示正在使用总线的主设备,仲裁器将记录该号码并在一段时间后重新发起传输
- 仲裁器授权其他主设备使用总线
- 如果其他主设备也出现了分割传输需求,仲裁器允许嵌套的分割传输
- 从设备准备完成传输时拉高HSPLITx信号里的对应位
- 每个时钟信号HCLK上升沿,仲裁器读取HSPLITx信号并重新授权对应的访问总线的主设备
- 仲裁器授权分割的主设备总线后,主设备可以重新尝试传输,如果有优先级更高的设备正在使用总线,分割传输不能打断
- 完成传输
AHB总线只允许每个总线主设备有一个未完成的处理,如果任何主设备模块能够处理多个未完成的处理,那么它需要为每个未完成的设置额外的请求和授权信号;但是一个具有分割交易能力的从设备可能会接收比他能并发处理传输还要多的传输请求,如果从设备出现来不及响应的请求,可以只记录主设备号来发出分割响应,之后等到设备完成当前工作再接收传输
分割交易时,需要警惕总线死锁的情况:如果多个不同的主设备同时尝试访问同一个从设备,但从设备发出的分割或重试响应表示从设备不能处理他们时,就可能发生死锁。为了避免死锁,仲裁器应当记录已经处理和发出分割响应的传输请求,从设备不需要锁存地址和控制信息,而是记录特定主机设备发出的传输请求,这样同时可以避免总线不安全因素:如果从设备不记录应该发出分割交易请求的主机,外来设备有可能在总线分割交易中间获取从设备回传的数据。
协议建议:分割交易中从设备发现主设备号不一致时,应该选择以下几种响应方式之一:
- 错误响应
- 传输对应信号给仲裁器
- 向总控制器发出系统级中断
- 执行完全的系统复位
AHB位宽
AHB协议允许8、16、32、64、128、256、512、1024位宽的数据总线,但是大多数用户都会使用32位~256位的总线
只需要在总线外部加入转换逻辑即可实现宽总线传输数据到窄从设备
传输时需要保证:
- 将待传输数据分成两份
- 同时传输;两份数据,但让从设备串行接收数据
这样就能实现1/2位宽的数据传输
但是如果要在窄总线上实现宽从设备的数据传输,就要在外部转换逻辑的基础上加入多路选择输入总线和复制输出总线电路,也就是说主设备的指令译码和从设备的返回数据都要加入额外的处理电路
AHB复位
HRESETn是AHB协议中唯一的低电平有效信号,并且是所有总线设备的复位源
AHB总线采用异步复位
但是复位可以在HCLK上升沿被同步撤销
需要保证复位期间主设备信号可控,并使用HTRANS[1:0]信号表示空闲
一套开源的AHB总线实现
GitHub上的一套开源AHB总线实现,上述代码全部以该repo为例
感兴趣的读者可以翻阅源码
AXI4规范
AHB总线和APB总线相关内容可以参考知乎上面@桔里猫的简介,本博文也参考了一部分
下面再介绍现代FPGA/SoC中常用的AMBA总线:AXI4总线
对比AHB总线,AXI4总线通过猝发交易机制实现了高性能、大吞吐量的数据传输。
AXI即Advanced Extensible Interface,是ARM公司提出的AMBA3.0协议中最重要的一种总线协议,面向高性能、高带宽、低延迟的片内传输。它的地址位、控制位、数据位相互分离,支持不对齐的数据传输,同时在猝发交易(突发传输)中只需要首地址。
AXI重要的三个特色就是分离的读写数据通道、支持显著传输访问和乱序访问、更加容易就行时序收敛,满足超高性能和复杂SoC设计的需求
AXI4包括了三个子总线协议:
- 标准AXI4:针对高性能内存映射(high-performance memory-map)要求实现的总线
- AXI4-Lite:用于低吞吐率内存映射(low-throughput memory-map)通信的总线(例如操作控制和状态寄存器),具有较小的面积,其中与标准AXI4最大的区别是突发(猝发)传输不受支持
- AXI-Stream:用于高速数据流的总线(比如视频信号、大量传感器数据通信),完全移除了对地址周期的要求,并允许无限制的突发数据尺寸,大大强化了传输周期的吞吐量,但是失去了内存地址映射的能力
可以这样理解三个协议:
AXI就是AHB的高速强化版,专用于CPU和缓存、内存的通信;Lite则是介于AXI与AHB速度之间的“青春版”,可以用于CPU控制较远的寄存器,或在小IP中使用以减小面积;Stream就是一个没有寻址功能的“管道”,数据管子进管子出,因为没法寻址所以也只能一对一传输
注意:AXI可以“向下”兼容AHB和APB接口
AXI综述
在硬件层次,AXI4允许每个AXI主从对使用不同的时钟。 此外,AXI协议允许插入寄存器片(通常称为流水线级)以帮助实现时序收敛
AXI总线共有5个单方向通道,分别是
- 读地址通道(read address channel),用AR标记
- 写地址通道(write address channel ),用AW标记
- 读数据通道(read data address channel),用R标记
- 写数据通道(write data channel ),用W标记
- 写响应通道(write response channel )用B标记
每一个通道都包含了一组信号线,这些线的作用不同,位宽大都可以自定义,但是每个通道都会包含两根握手信号线:READY和VALID。握手机制是AXI总线中主机和从机之间建立传输的一个标志。VALID信号来自于源设备(source),READY来自于目标设备(destination),所有的信息源设备都会发送一个VALID信号,去展示出自己通道内此时的东西是否是有效的。
传输建立之前,目标设备都会发送一个READY信号,去展示自己是否准备好,当VALID和READY都是高电平的时候,对应的通道就被“使能”,传输也就建立了
所以说通道握手就是源设备发送VALID,目标设备发送READY
每个通道都有不同的功能:
读地址通道AR和写地址通道AW用于在本次传输中收发所需的地址和控制信息
读数据通道R携带主机要读出的数据
对于读过程来说,从设备是源设备,主设备是目标设备,所以在R通道内部,VALID是从设备发出,READY是主设备发出
写数据通道W把主设备要写入从设备的数据转发给从设备
写响应通道B用于提交写处理的响应,需要注意:AXI协议规定所有写处理都需要返回响应信号
下图展示了AXI4读事务中读地址通道读数据通道的工作状态
在Xilinx Vivado中,给出了一套AXI总线的实现,如下所示
看起来很复杂,但实际上上面大多数接口都可以合并为主机AXI通道接口(AXI4_MASTER_M_AXI)和从机AXI通道接口(AXI4_SLAVE_S_AXI),同时还具有两个全局的接口:复位端ARESETN和时钟端ACLK,也就是如下图所示,两边带加号的两套接口就是主机和从机的AXI通道接口,带ACLK、ARESET的信号分别是全局(INTERCONNECT开头)、主机(M00开头)、从机(M00开头)的时钟和复位信号
总线信号
这部分简单介绍信号的内容,具体什么信号负责什么工作会在后面的数据读写部分介绍
全局信号
ACLK:总线时钟
这是一个单bit信号,系统会根据总线时钟在上升沿触发
一个常见的问题,自行设计的AXI总线有时候会在主设备输入和从设备输出端有意或无意地接入组合逻辑电路,这样容易导致时序混乱。比较常用避免这一情况的方法是在输入输出AXI时钟接口的信号线上接入reg型变量,引入时序要素
ARESETn:总线全局复位,低电平触发,支持异步复位,但是要让这个复位信号触发,还是同步于时钟,这就是所谓的
异步复位同步触发
需要注意:协议要求复位高于一切,也就是说在复位期间,ARVALID和AWVALID同时还有WVALID需要全部置低,不允许有用信号产生
上面的两个总线要求看着很复杂,实际上代码实现就是
1 | always @(posedge clk or negedge n_rst) begin |
无论是主机和从机都应该加上这段复位代码
写地址通道AW总线信号
写数据通道W总线信号
写数据通道支持8、16、32、64、128、256、512、1024位宽,每8位有一个字节通道写选通控制信号WSTRB,用于表示数据总线上有效的字节
写响应通道B总线信号
写响应通道提供了用于从设备完成写入响应的方法,每个响应都对应于一次猝发传输或普通传输的完成,而不是对应于每个传输的数据
BRESP返回值的二进制表示如下
BRESP[1:0]值 | 响应含义 |
---|---|
00 | OKAY,写入成功 |
01 | EXOKAY,独占式存取成功 |
10 | SLVERR,从机已经和主机建立了连接并接收到数据,但出现错误 |
11 | DECERR,解码错误,互联模块无法正确译码并连接到从机 |
读地址通道AR总线信号
读地址通道和写地址通道机制相似,因此具有类似的总线信号,含义都一样
读数据通道R总线信号
支持8、16、32、64、128、256、512、1024位宽,使用读响应RRESP表示读操作完成的状态
握手信号
对于五个通道而言,它们都使用各自的READY和VALID实现握手机制去控制五个通道内部的处理,包括传递地址、数据及控制信息。这个两路双向控制的机制让主设备和从设备都能够控制通道内部的信息交换速率。
源设备能够产生valid信号告知目标设备通道内部信息是否有效;目标设备能够产生ready信号告知源设备是否准备好了接收信息。如果要完成一次传输(一拍)则需要两个信号都是高电平。
和时钟、复位信号类似,ready和valid信号之间不能有组合逻辑链接——就是两个信号其实相互无关,只是他们共同决定传输是否开始,即valid产生是因为信号有用而产生,而不是有ready信号出现才产生;类似地,ready信号是因为目标设备做好了准备才产生,并不是valid有效而产生),这也就是所谓的独立握手
为了避免死锁,握手信号还存在一定依赖关系,最基本的两条依赖就是:
- valid信号不依赖于交易中其他元件的ready信号
- ready信号能够等待确认valid信号
需要注意:依赖关系是指握手建立的条件,而不是信号产生的条件
读写传输中分别要满足以下依赖关系:
协议中给出了几个典型情况下对于握手信号的要求:
如果valid信号先于reday,这个情况必须要主机保持有效信号直到从机准备完毕
下图给出了这种情况下的时序图
源设备在T1时刻之后产生了有用的信息,于是拉高VALID信号,T2时刻时钟上升沿处采样,系统才知道信息有效;而目标设备在T2时刻之后才准备好,同时发送ready信号,错过了T2时刻上升沿,所以源设备必须保持它携带的的信息稳定知道T3时刻,此时valid、ready握手信号都为高电平,于是在T3时刻上升沿传输发起
如果ready先于valid,这个情况必须要让从机等待主机发出有效信号
T1时刻之后从机准备好,READY信号开始拉高,到了T2时刻的上升沿,系统知道目标设备准备好了;但是主设备在T2之后才生成有效数据并将VALID信号拉高,所以真正有效的传输要等到T3时刻
如果ready和valid同时到来,这个情况必须要等待到下一个时钟上升沿
这个很容易理解,时钟信号上升沿采样,双方都没有拿到valid、ready,自然要同时保持直到下个上升沿
总的来说就是源设备的VALID信号只要没准备好就可以拉低,READY拉高拉低标准取决于目标设备,和VALID无关,所以这也印证之前讲的VALID和READY之间不能有组合逻辑。
协议标准中不建议随时把READY拉低,因为在READY先到的情况下需要使用一个上升沿确定READY拉高,然后必然又要花费一个上升沿等待VALID,这样完成握手其实已经等待了两个时钟周期
总结一下,AXI总线的握手规则是为了有效传输而设立的,从机和主机的通讯需要建立在有效信号VALID和准备信号READY都拉高的基础上,如果主机向从机提出读写请求,就相当于主机先准备好,然后等待从机发出有效数据;如果从机向主机提出读写请求,就相当于从机先准备好,然后等待主机发出有效数据——这些信息都是通过握手通道实现数据交换的
AXI猝发传输
AXI4协议规定了3种猝发传输,一次猝发只能传递4KB的数据,根据数据总线宽度变化,决定有多少拍(transfer)
这个数据量是根据总线宽度决定的
假设我们有32位数据线,则每一拍实际传输4个字节数据,这时候一共需要128拍才能传完4KB的数据,所以我们把128叫做猝发传输长度,也就是发起了多少次传输/拍(transfer)。猝发传输长度是根据总线宽度和这个上限4KB共同决定的——当然也可以不传满
- 固定猝发
- 递增猝发
- 回卷猝发
猝发传输类型由ARBURST和AWBURST信号选择,如下所示
ARBURST,AWBURST | 猝发类型 | 描述 | 访问 |
---|---|---|---|
00 | 固定 | 对固定地址进行猝发访问,按顺序进行数据压栈/入队 | FIFO类型 |
01 | 递增 | 地址递增地进行猝发访问,一次完成一个序列的传输 | 普通顺序寄存器 |
10 | 回卷 | 地址递增地进行猝发访问,但在边界时返回低地址 | 高速缓存行 |
11 | 保留 | N/A | N/A |
固定猝发传输是指每一次传输都是重复的往同一个地址写东西,数据会按顺序“塞进”对应地址
递增猝发传输是指每一次传输都在上一次传输地址的基础上增长,地址增长多少取决于猝发传输容量(burst size)
假设每一次传输的burst size都是32位(4个字节),下一次的传输地址会增加4,地址一点点增长,数据也对应写入
这种方式常用于一般的存储单元顺序访问,比如ram读写
回卷猝发传输(也称为回环猝发传输)是在递增猝发传输的基础上,当写到最高地址的时候又回到最开始的最低起始地址
这种方式常常用于处理高速缓存的访存
比较特殊的是回卷猝发,要求起始地址必须对齐传输大小且促发长度只能是2、4、8或16,更大的猝发传输只支持递增类型,回卷和固定类型只限于小于16拍的猝发传输
递增传输支持1到256拍的传输;其他猝发传输只能支持1到16拍,这样为了保证数据总量不超过4KB
需要再次强调:猝发传输容量(burst size)实际上是数据总线位宽,猝发传输长度(burst length)是拍数,两个的乘积就是数据的总量,不能超过4KB
数据读写
之前已经说过,AXI4总线包含五个基本通道,分别处理地址读/写(AR、AW)、数据读/写(R、W)和写响应(B)
在写事务过程中,AXI总线将采取如下图所示的方式
需要使用到W、AW、B三个通道
而参考之前介绍过的读事务示意图,读操作中只需要使用R、AR两个通道,不难发现AXI通道可以实现同时读写
在读数据过程中,主设备发出请求后首先进行主从设备仲裁,仲裁器通过请求后,主设备才能和从设备建立连接,然后主设备通过AR通道将要读取的数据地址发送给从机(预先要进行握手),主机进入等待状态,从机根据指令将数据通过R通道返回主机,在传输过程中如果使用了猝发传输,那么burst size猝发传输容量就是上图所示每次传输的数据大小,transfer拍就是上图中传输的次数,二者乘积要保证不大于4KB,传输过程中要保证开始传输的时候进行握手,后续传输中握手信号保持有效状态(RVALID=1,RREADY=1),在结束读取之前的最后一个数据包发出后(最后一次传输结束前),从设备要发出一个结束信号,将RLAST信号拉高一个周期表示传输结束
在写数据事务中,需要主设备通过AW通道向从设备发起写入请求并传输写入的地址,猝发类型也会一并在这个阶段通过AW通道传输给从设备,随后从设备会等待主设备的写入数据,主设备握手完成后就会通过W通道向从设备写入数据。等待所有数据写入完成后,从设备会通过B通道向主设备发送写响应,标志数据的写入状态。需要注意,最后一个数据包写入后(最后一次传输结束前),主设备需要拉高WLAST信号来表示传输结束
强调一下WSTRB表示写选通控制信号
只有WDATA中数据有效(即WVALID高电平)时,才能发起写传输并写入有效数据;如果WVALID为低电平(数据无效),则这个时候WSTRB可以为任意值,但是协议中建议:若WVALID为低电平,WSTRB最好维持上次的值或是统一变为低电平以维护代码逻辑、增加系统稳定性、节省动态功耗
在整个传输过程中,主设备往往会向从设备确认ID,也就是通过AWID、BID、ARID、RID这四个4位的信号进行ID匹配,要求:
- 从设备在响应通道中返回的BID必须匹配主设备在写入过程中发送给从设备的AWID
- 从设备在读数据通道中返回的RID必须匹配主设备发送读取地址时一并发送给从设备的ARID
这个要求是AXI标准协议独有的,在AXI-Lite总线中不需要确认ID,这就是为什么AXI标准主机不能兼容AXI-Lite从机;但AXI-Lite主机可以兼容AXI标准从机
总线互联
AXI总线支持以下几种形式的总线互联结构,可以组织成AXI总线矩阵
直通模式
单主单从设备互联,AXI不执行任何转换或流水线功能,无总线延迟,不消耗逻辑资源
只转换模式
单主单从设备互联,AXI执行不同的转换或流水线功能,主要包括
数据宽度转换:将宽数据转换为窄数据
时钟速率转化:跨高速/低速设备传输数据
总线标准转换:标准AXI转AXI-Lite、AXI4转AXI3等
流水线传输:对寄存器或FIFO执行访问
该模式下AXI互联不包含仲裁、解码或布线逻辑,但可能产生延迟
N-1互联模式
多主一从设备互联
这个配置中需要使用一个仲裁逻辑,但是并不需要地址译码逻辑
当然,它也可以执行数据宽度和时钟速率转换
1-N互联模式
一主多从设备互联
常见于处理器和片上内存/Flash连接,这需要一个存储器映射的从外设,AXI总线不执行仲裁,但是需要一个解码逻辑
N-M互联模式
多主多从连接
这种模式下,AXI提供共享地址多数据流(SAMD)拓扑结构和稀疏互联开关拓扑结构
共享读写地址仲裁结构中将读写指令交由两个仲裁器进行分配;稀疏互联开关拓扑结构则使用两套独立的多路选择器-译码器电路控制指令
AXI4-Lite
AXI4-Lite简称AXI-Lite,是AXI4接口的子集,专用于片上寄存器通信,它的规模较小,因此设计和验证要求也更少,相对于AXI4标准协议,它的特点有:
- 所有传输的猝发长度(burst length)为1,也就是说AXI-Lite不支持猝发传输
- 所有访问数据宽读和数据总线宽度相同
- 支持32位或64位数据总线宽读
- 不支持互斥性操作
AXI-Lite接口信号线相对较少,如下所示
AXI-Lite作为主设备接口,可以直接兼容AXI标准从设备;但是AXI标准主设备大多需要经过AXI2AXI-Lite转接才能兼容AXI-Lite从设备,因为AXI主设备会要求从设备返回AXI ID,但AXI-Lite不需要
可以直接理解成AXI标准主设备=AXI-Lite主设备,但AXI-Lite从设备<AXI标准从设备,这也符合AXI-Lite减小从设备规模占用的设计目的
AXI-Stream
AXI-Stream用于连接直接交换数据的片上器件,接口将产生数据的设备视为主设备,将接收数据的设备视为从设备,在二者之间建立数据流通道(有点类似于Linux里面的管道传输概念,主设备的输出数据会直接输入从设备)。AXI-Stream不支持内存映射!
AXI-Stream可以允许无限制的突发传输,直观来说就是AXI-Stream主机可以一直向从机写数据
不过AXI-Stream也可以支持多主一从的连接,允许建立互联结构,这样该结构可以执行扩展、压缩和路由操作
正如它的名字所说,AXI-Stream常用于各种基于数据流结构的片上外设
它的信号表如下所示:
ACLK、ARESETn大家都熟悉,不再多介绍。TVALID和TREADY信号是AXI-Stream的专用握手信号。主设备不允许在确认TVALID前确认TREADY,一旦取人TVALID就必须一直保持该状态直到握手完毕;从设备允许在确认TREADY前等待确认TVALID,不过在TVALID信号确认前从设备可以释放TREADY
这个握手原则是为了保证从设备只需要快速输出数据而主设备应该及时接收
AXI-Stream的结构和AXI标准协议中的写数据通道很类似——事实上Stream就是把AXI标准协议中的W通道拿出来,这也就是为什么它不支持内存映射。
AXI总线IP核使用
整套AXI的IP主要包含三部分
- 主机
- 从机
- AXI连接器
主机IP实现了AXI主机与主设备寄存器或控制器的连接,从机IP实现了AXI从机与从设备寄存器的连接,二者都依附主设备或从设备存在;而AXI连接器则表现得像一个独立的模块,一个标准的AXI连接(直通模式)如下所示
事实上AXI连接器这个IP还可以进一步拆分,用不同分工的子IP实现各种需要AXI总线完成的功能,在Xilinx的FPGA设备中提供了如下几类IP:
- AXI Register Slice:用于流水线操作的AXI总线上缓存(寄存器),常用于处理关键时序路径
- AXI Data FIFO:带FIFO的AXI总线,可用于跨时钟域或数据流缓存
- AXI Interconnect IP/AXI SmartConnect IP:用于内存映射地连接片上外设,SmartConnect IP相对于Interconnect IP提供更高带宽和更低延迟,但是占用更多片上资源
- AXI Direct Memory Access(DMA) engine:带内存映射的DMA通道,可用于实现AXI-Stream到AXI标准协议的转换
除此之外还有一系列具有辅助功能的AXI IP设备,部分设备已经被集成到了AXI Interconnect IP/AXI SmartConnect IP中
- AXI Performance Monitors and Protocol Checkers:用于调试和分析片上外设问题的特殊AXI连接器
- AXI Verification IP:用于仿真验证和性能分析
- AXI Crossbar:连接多个相似主机和多个相似从机(低配版总线矩阵)
- AXI Data Width Converter:AXI总线宽度(也就是之前说的总线大小axi-bus-size)转换
- AXI Clock Convertor:可以跨时钟域连接主从的AXI总线
- AXI Protocol Convertor:将AXI4标准协议、AXI-Lite、AXI3主机和另一个不同AXI协议从机相连的AXI协议转换器
- AXI MMU:为AXI Interconnect IP提供地址解码功能
Vivado还支持封装带有AXI从机接口的IP核,从而实现基于AXI的片上系统
其他资料
上述资料根据Xilinx的Vivado AMBA总线使用手册和ARM AMBA协议原文整理编辑,同时参考了视频讲解和其他网络资料。如果有兴趣的读者可以自行翻阅Github搜索AXI总线的实现,这里不再介绍