第一章  AMBA总线介绍

1、AMBA总线协议总览

AMBA(Advanced Microcontroller Bus Architecture)总线协议是一种面向高性能嵌入式微控制器设计的片上联接标准。

AMBA总线(截至AMBA2.0)确定了三种总线标准:

AHB:(Advanced High-performance Bus)

ASB:(Advanced System Bus)

APB:(Advanced Peripheral Bus)

其中,

AHB总线面向高性能、高时钟频率的系统模块。AHB通常作为高性能系统的主要总线,上面主要挂载处理器、片上存储器和片外具有低功耗外设宏单元接口的存储器;AHB还通过综合和自动化测试技术确保其在设计flow中的高效使用。

ASB总线面向高性能系统模块,在某些并不需要AHB那么高速度的场合,作为AHB的替代品来出现。

APB总线面向低功耗外设,其设计用于外设最小化功耗和减小外设复杂性,其可以与AHB或这ASB总线中任意一个系统总线连接

2、基于AMBA的微控制器

基于AMBA的微控制器通常包含一个高性能的系统主总线(system backbone bus),通常为ASB或AHB,上面挂载CPU、片内存储器和DMA设备,AHB或ASB总线在挂载在它上面的传输主体之间提供了高带宽的接口。同时AHB或ASB总线上也挂载了Bridge;APB总线上挂载低功耗外设,向上挂载在Bridge上。(AHB和ASB的区别:AHB支持Split和burst,而ASB不支持)

APB总线上的外设通常如下:

1、接口为memory-mapped register

2、没有高带宽接口

3、可以被编程控制

外部内存接口是一种专用的接口,只含有低带宽的数据通路,但是也支持test mode。

3、术语(Terminology)

Bus Cycle:总线时钟周期的基本单位。对于AHB和APB来说,总线周期指的是从上升沿到上升沿的时间;对于ASB来说,总线周期指的是从下降沿到下降沿的时间

Bus transfer:在ASB和AHB总线中,总线传输(bus transfer)指的是对于一个数据的读写操作,通常会花费一个或多个总线周期(bus cycle),从slave得到一个“完成响应”意味着bus transfer的结束。ASB总线的传输大小有Byte(8bits)、halfword(16bits)和word(32bit);在AHB总线中还包括64bits和128bits;APB总线传输时通常只需要2个bus cycles;

burst operation:指的是由master发起的1次或多次数据交互,其数据交互时地址空间是递增的,递增大小等于bus transfer的宽度。在APB中不支持Burst。

4、AHB总线介绍

AHB是AMBA的新一代总线协议,用于满足高性能可综合设计的需求,支持多个bus master和大带宽运行。

主要性能如下:

通常情况下,AHB总线系统中要包含至少一个处理器和test interface,通常还会有DMA和DSP也作为总线的master

外部内存接口、APB bridge和任何内部存储器通常都作为AHB总线上的slave存在。系统中的其他外设也会作为AHB的slave,但是通常低带宽的外设都被挂载在APB总线上,而非AHB总线上。

通常一个AHB系统设计包含如下部分:

AHB Master:通过提供地址和控制信息来初始化读写过程,同一时刻仅允许有一个master在使用总线

AHB Salve:响应在地址空间内的读写信号。

AHB Arbiter:确保同一时间只有1个master可以启动数据传输过程。虽然仲裁协议是固定的,但是仲裁算法是可选的,以用户的需求为准,如最高优先级仲裁和平均仲裁。(一个AHB总线仅包含一个仲裁器,在单master的系统中,仲裁器就不太重要了。)

AHB Decoder:解码每次transfer中的地址信号,然后给对应的slave提供cs片选信号。所有的AHB应用中都需要一个解码器。

5、ASB总线介绍

ASB是AMBA的第一代总线协议,位于APB总线的上层 。

主要性能如下:

ASB Decoder:解码传输过程中的地址信息,产生正确的片选信号。除此之外,当没有transfer请求时,decoder还用于确保总线处于运行状态。

其他部分均与AHB总线的描述一致,这里就不再赘述

6、APB总线介绍

APB总线可以认为是AHB或ASB总线的一个slave设备。

APB bridge作为一个slave模块,代表本地外设总线处理总线握手和控制信号重定时(retiming),在系统总线的一开始就确定APB总线,可以充分利用AMBA总线的系统诊断和测试方法学。

APB总线通常用于低带宽且不要求pipeline 总线接口高性能表现的外设。

最新的APB协议规所有的信号交换都是在时钟信号的上升沿。(ASB总线是下降沿)

APB改为上升沿之后有以下好处:

1、高频运行更容易实现了

2、具体操作和时钟信号的占空比无关(是不是可以认为通常情况下时钟信号的初始电平都是高电平)

3、AHB和APB都使用同一个边缘的时候,静态时序分析也更容易做了

4、在做自动化测试插入时不需要考虑其他问题

5、很多专用集成电路(ASIC)库对于上升沿的寄存器有更好的选择

APB结构中通常只包含一个APB bridge,用于将AHB或ASB的transfer信号转换至APB总线上的slave设备

APB bridge提供锁存所有的地址信号、数据信号和控制信号,同时提供了一个二级的解码器用于给APB总线上的设备提供片选信号。APB总线上的所有设备都是slave设备。

APB总线上的设备具备如下特性:

如何选择合适的总线

在使用系统总线的时候,推荐使用AHB总线。因为它和APB总线都是上升沿有效的,且具有高性能表现

在使用外设总线的时候,可以让外设同时支持AHB总线和ASB总线,但是通常不这么做,主要有以下原因:

1、当一个外设包含了数量庞大的宏单元时,同时支持两种总线所增加的部分会增加功耗和降低系统性能

2、当进行时序分析的时候,总线中最慢的元件决定了总线的最好表现(类似水桶原理)

3、很多简单的外设单元只需要锁存地址和控制信号,而一些高带宽的宏单元却需要考虑从Pipeline 信号中获益(意思是外设有简单复杂之分)

4、很多简答的外设单元只需要检测到上层的片选信号和读写总线操作,而不需要广播高频时钟信号至每一个外设(意思是外设对外设bridge的需求也有简单复杂之分)

AHB和ASB接口主要用于以下场合:

注意:不光是master要挂载在AHB总线上,DMA需要访问的slave和一些需要高带宽的slave也要挂载在AHB总线上。

APB接口主要用于以下场合:

注意:挂载在APB总线上的通常是寄存器映射的slave设备。(或者需要局部时钟的设备或需要比较窄的总线带宽的设备)

AMBA协议提示

AMBA协议只是详细介绍了时钟cycle层面的总线协议,而与片上具体的实现技术无关

AMBA协议中没有规定具体的电气特性,因为这个完全取决设计方案所选择的量产工艺和技术。

AMBA协议只规定了各种信号在clock cycle层面的行为,而没有规定具体的时序要求,因为时序要求取决于实现的工艺和运行的频率,这也可以让设计者能够更加灵活地分配各个模块之间的时序预算。

第二章  AMBA信号

信号名称中的小写字母n表示低电平有效,否则都表示高电平有效

信号命名

AMBA协议的每个信号前面都有一个前缀,表示信号的类型

在AHB信号中:

前缀H:表示这是一个AHB信号;如HREADY表示AHB协议中表征每次数据传输完成的信号,高电平有效;

在ASB协议中:

前缀A:表示这是ASB总线master和仲裁器arbiter之间的单向信号

前缀B:表示这是一个ASB信号

前缀D:表示这是一个ASB解码器的单向信号 如BnRES表示ASB协议的复位信号,低电平有效

APB协议中:

前缀P:表示这是一个APB信号;如PCLK表示是APB的主时钟信号

AMBA AHB信号列表

需要详细介绍的信号如下:

HSIZE[2:0]:

表征的是transfer 时的大小,HSIZE共7个数值,一共表示8bit、16bit、32bit、64bit、128bit、256bit、512bit、1024bit

HBURST[2:0]:

表征的是burst的类型以及是否构成burst。如下所示:

increment burst表示累积式地址burst,下一次数据写入的地址为上一次地址的基础上增加一个固定值

wrapping burst表示包装式地址burst,下一次地址计算遵循一定的规则,这样就保证了传输地址构成了一个完整的圈。这个圈的总长度就是burst数据的总长度,起始地址可以是这个圈里面的任意一个点。

HPROT[3:0]:

多Master运行时的额外信号

带有x后缀的表示此信号是点对点传输的,如果有多个master,也就对应地有多个此信号

一条总线上最多可以有16个master,由HMASTER[3:0]可以看出来、

HSPLITx[15:0]表示此slave允许哪几个Master重新发起一次split transcation,这里可以理解为每个Master都是one hot编码,如果这个寄存器有多个位为1,则表示允许多个Master

AMBA ASB信号列表

AMBA APB信号列表

第三章  AMBA AHB

AHB总线连接

AHB总线使用的是一种称为“中心式多路协调器”的连接方案。

Master方的data全部连接至data Arbiter,全部的address连接至address arbiter。以此确定到底发给哪个slave

Slave方的read data全部连接至decoder,以此确定到底将数据发送给哪个Master

AMBA AHB运行概览

遵循如下步骤

1、AHB 的Master向Arbiter发送请求信号

2、Aibiter grant来自Master的请求信号

3、AHB Master驱动address signal和control signals,通常花费一个cycle。(control signal究竟包含哪些信号之后会详细解释)

4、Master驱动wdata signal将数据从Master传输至Slave,或Slave驱动rdata signals将数据从slave传输至master。通常花费1个或多个cycle。

address信号是无法被延长的(extended),而data信号是可以通过HREADY信号来延长。当HREADY为低电平时,在transfer data过程中被插入一个wait state。

5、每一个burst传输完毕后,Slave用HRESP[1:0]信号来表示响应。

【注意】通常情况下,arbiter会等上一个master的burst完成之后再允许另外一个master获取总线控制权。但是在某些情况下,为了避免仲裁延迟,可能会直接终止一个Master的burst,然后将总线控制权交给两一个Master。此时此Master就要re-arbitrate来完成剩余的burst。

基本传输transfer

address phase只会持续一个cycle,但是data phase由于HREADY的低电平,可能会持续多个cycle。

【理解】这里的data phase应该理解为单个burst可能会被延长,而不是整个数据传输过程。

时序分析

1、在HCLK的第一个上升沿,Master开始改变HADDR和control上的数据。(这个 改变等一个延迟才能生效,就是图中灰色的部分)

2、在HCLK的第二个上升沿,Slave采样HADDR和control上的数据,明白了Master要干什么。此时Master如果要写数据的话,第二个上升沿之后,Master就应该将数据驱动在HWDATA线上。此时Master如果要读数据,则第二个上升沿之后,Slave就要将数据驱动在HRDATA线上。(灰色的部分是从敏感到上升沿至驱动信号生效之间的延迟)

3、在HCLK的第三个上升沿。如果之前Slave确定Master要写数据,则此时去采样HWDATA上的数据;如果之前Slave确定Master要读数据,在此时就应该将下一个数据驱动在HRDATA线上(根据control signals)。

4、依次类推,直至结束

【重点】因为采用pipeline的形式,所以每次的address phase都是在上一次transfer的data phase时间内。

如果Slave中的HREADY为电平,则意味着:

1、在这个上升沿Slave无法采样来自Master的WDATA值,因此这个时钟之后,HWDATA上的信号不变,等下一个上升沿的时候再判断HREADY的信号。

2、或者在这个上升沿Slave无法驱动给Master的RDATA值。因此此时Master不要采样HRDATA的信号,等下一个上升沿的时候再说

(意思就是Slave告诉Master,这个上升沿我没空收你的数据,你保持着;我也没空发给你数,你不要采样)

这一个数据传输的时间被延长了,称为extended cycles

由上图可以看出,extended cycle的时候,延长的是当前的data signals,产生的副作用(side-effect)是对应的pipeline中下一个address和control也被延长了(上图中A和C地址的都没有wait,只有B的存在一个cycle的wait)

Control signals

Control signals主要包含以下的signals:

HTRANS[1:0]:确定数据传输的类型

HBURST[2:0]:确定burst的类型和大小

HWRITE:确定数据传输的方向

HSIZE[2:0]:确定每次burst时传输的数据大小

HPROT[3:0]:确定传输时的一些额外信息,如传输类型,传输模式,是否有buff以及内存的类型。

HTRANS[1:0]:

IDLE:表示某个Master获得了总线控制权,但是不想传输数据了。此时Slave的response应该为OKAY

BUSY:表示Master想要在burst传输的过程中插入IDLE,表示Master会继续burst传输,但是burst可能不会立即到来。此时Slave的response为OKAY(Slave通过HRADY中的低电平来插入延迟,而Master通过HTRANS中的busy来插入延迟)

NONSEQ:表示burst传输时的第一个transfer

SEQ:表示burst传输时剩余的transfer,此次transfer与之前的transfer是相关的。

图例解释:(因此在Master和Slave发送数据时,都需要考虑对方的延迟请求,Master通过HTRANS的busy状态来请求,Slave通过HREADY的低电平来请求延迟)

第一个busy表示Master想要延迟一个cycle,则WDATA和RDATA上的pineline都停一个cycle。

逻辑上可以认为当写入数据时,Master在上升沿先判断HTRANS的状态,再确定上升沿之后要不要在HWDATA上写入数据。而Slave线先判断HTRANS的状态,再确定下一个上升沿要不要采样HWDATA的数据;

逻辑上认为当读入数据时,Master在上升沿先判断HREADY的状态,再确定上升沿之后HTRANS和 HADDR的状态要不要改变。Slave端要根据上升沿之后自己确定的HREADY状态,确定下一个上升沿在HRDATA上要不要驱动数据。

HBURST[2:0]

【重点】能够分配给单个从机的最小地址空间是 1KB。所有总线主机必须被设计为不能执行超过 1KB 地址边界的增量传输,因此确保了一个突发绝不会超过地址译码的边界。

INCR的意思是burst的每次beat就按照HSIZE来transfer,但是究竟beat几次,还不知道。HADDR的increment就按照HSIZE来确定。直到下一个HTRANS中出现NONSEQ时开启另一次burst。如下图所示:

上述列表中所描述的burst的大小指的是burst的beats数量(可以理解为没有延迟时的cycle数量),而不是Byte的数量(Byte的数量=Hburst*HSIZE)

对齐原则:在一个burst中的所有transfer的地址都必须对齐于transfer的大小(即HSIZE)。word传输时,地址必须是字对齐的(一个字中含有4个Byte,字对齐的意思是地址能被4整除,即地址二进制最低两位为00),half-word传输时,地址必须是半字对齐的(一个半字中含有2个Byte,半字对齐的意思是地址能被2整除,即地址二进制最低位为0)

【注意】能被4整除,意味着向右平移两位,不产生余数,则二进制最低两位必须为0;能被2整除,意味着向右平移以为不产生余数,则二进制最低位必须为0;

BURST提前结束(termination)

Slave可以通过监控HTRANS信号来确定何时提前结束一个burst。

如果HTRANS中的信号为SEQ或BUSY,则表示burst正常运行;如果HTRANS中的信号为NON-SEQ或IDLE,则表示新的burst已经开始,前一个burst必须要停止了。

【注意】HADDR中的地址指的是起始地址,而不是结束地址。

当一个Master因为丧失了总线控制权而未能完成burst的时候,当他下次获取总线控制权的时候,必须rebuild的burst。

HWRITE

与address signal的时序相同,在整个burst期间保持不变。

HWRITE为高表示从master写数据,数据驱动HWDATA[31:0];

HWRITE为低表示从Slave读数据,数据驱动HRDATA[31:0];

HSIZE[2:0]

与address signal的时序相同,在整个burst期间保持不变。

HPROT[3:0]

提供一些总线传输时的额外信息,也能够够为其他任何希望实现一定程度保护功能的模块提供基础支持。

后四个选项是个具有内存管理单元的总线master所提供的。

并不是所有的Master都能够产生正确的保护信息,因此除非很有必须,否则Slave不要使用HPORT

地址解码(Address Decoding)

由上图可以看出ADDR Arbiter用来决定哪个Master的地址可以传输出来,ADDR Decoder用来从地址信息中判断哪个Slave被选中进行操作(用于产生HSEL_x信号)

通常情况下,Slave必须在HREADY高电平的时候,采样地址信号、控制信号和HSELx信号,表示目前的transfer还在进行中;

但是在某些情况下,当HREADY为低电平的时候,HSELx也可能被插入,但是被此HSELx选中的Slave也必须等到当前的transfer结束时才能改变状态。

可以被分配个一个Slave的最小地址空间为1kB,因此burst的时候地址绝对不能跨过1kB的界限,这样就保证了burst不会超过本身Slave的地址,传递到另外一个Slave的地址空间里面去。

在一个系统中,如果memory map没有被完全filled的时候,需要添加一个额外的默认slave,用于当访问不存在的地址空间(memory map中未分配给Slave的内存空间)时,由此default Slave给予response。

当访问不存在地址是,若TRANS信号为NONSEQ或SEQ,则default Slave回复ERROR response;若TRANS信号为IDLE或BUSY,则Slave回复Okay。通常情况下,default slave的功能也是central address decoder的一部分。

Slave Response

AHB协议中没有提供当transfer已经开始的情况下,Master想要cancel transfer的流程。

当某个Slave被选中进行transfer的时候,必须要提供response来表示transfer的状态。

Slave的response是通过HREADY和HRESP来实现的

HREADY

HREADY为高电平的时候,表示当前transfer可以结束,具体再看HRESP的状态

HREADY为低电平的时候,表示当前的transfer被延长了,插入一个或多个wait state。

每个Slave都必须有一个实现预定的wait state的最大值,超过这个最大值,此Slave就放开总线。

建议但不是强制要求,每个slave不要插入超过16个 wait state,以免单个Slave长时间占用总线。

HRESP

当Slave需要插入几个cycle的wait state来确定response的时候(HREADY低电平),则这几个cycle里面Slave给的回复必须是OKAY

【总结】

单周期response为OKAY,多周期response为ERROR、RETRY、SPLIT。

HREADY高电平+response OKAY :表示单个transfer的结束

HREADY低电平+response OKAY:表示单个transfer要被延长一个cycle(这个状态可以一直持续多个cycle,均表示extended,此时的response也必须是OKAY

HREADY低电平+response ERROR/RETRY/SPLIT:表示2-cycle response的第一个cycle

HREADY高电平+response ERROR/RETRY/SPLIT:表示2-cycle response的第二个cycle

【解释】为什么要存在2-cycle的response,是因为pipeline的要求。当Slave开始发送一份error、split或retry的response是,下一次传输的address已经发送到总线上了,2-cycle的response主要是为了给Master足够的时间来cancel这个address,从而在下一次transfer之前将HTRANS恢复至IDLE 状态(如下图所示,当pipeline中地址线已经将A+4的地址发送到bus上时,Slave发送了RETRY,意思是Slave未成功收到A地址的数据,需要将A再发送一次。因此Master需要一个额外的cycle将状态回到IDLE,然后重启一个transfer,从A开始传输数据)

对于 SPLIT 和 RETRY 响应接下来的传输必须取消因为在当前传输完成之前禁止下一次传输发生。(意思是SPLIT和RETRY response之后,当前的transfer是要被重复的,例如上图中重复了当前地址为A的transfer)。然而,对于 ERROR 响应,由于当前传输不被重复,所以可以选择完成接下来的传输。

也可以在2-cycle response之前再通过HREADY低电平+response OKAY的方式再extended一个cycle,如下图所示

Error Response

2-cycle response。当前的transfer不必重复,burst中的剩余transfer可以选择可以继续也可以停止。都是可以的。

Split and retry response

2-cycle response,当前transfer在重启后的burst中必须重复。当前burst中的剩余transfer必须停止。这两种回复都会让Master丧失总线控制权,进而让更高优先级的Master取得总线控制权。

Split和retry之间的区别:

1、对于RETRY来说,arbiter会继续使用常规的优先级方案,因此之后是享有最高 优先级的Master获得总线控制权

2、对于SPLIT来说,arbiter会调整优先级方案,将当前Master的优先级置于所有Master后面,即使是原本优先级比他低的Mmaster。为了Split的完成,当Slave有数据的时候,他应该通过某种方式让arbiter知道。(因此SPLIT给slave和arbiter都增加了额外的复杂度,但是优点是可以释放总线给其他的Master使用,而RETRY只能将让高优先级的Master获取总线)

对于Master来说,Split和RETRY没有什么区别,它还是一如既往地请求总线,直至完成所有的transfer或者被ERROR response给结束掉。

Data Bus

数据总线采用将读总线和写总线分开的结构,总线的最小宽度为32bit

HWDATA[31:0]:

1、当transfer被extended的时候,例如Slave的HREADY为低电平时,Master必须hold data valid直到transfer完成(完成时HREADY为高电平)

2、transfer传输时的地址必须以HSIZE来对齐

3、当传送的数据宽度比32bit小的时候,根据大小端规则,每次transfer的时候会选择不同的bus来传输。Slave负责在合适的总线上sample获取数据。

AMBA协议中并没有规定所使用的大小端规则,因此通信时务必保证Master和Slave使用相同的大小端规则。

上面的规则可以扩展为:当burst传输时,HSIZE小于data bus width(即使被扩展为大于32bit)时,每个burst传输时所用的Byte Lanes是不同的。

HRDATA[31:0]:

1、当transfer被extended的时候,例如slave的Hready为低电平时,slave需要在transfer的最后一个cycle提供valid data;

(transfer的最后一个cycle时HREADY为高电平)

2、当传输过程中的HSIZE数据宽度小于总线宽度时,slave需要选择合适的byte lane来传输数据,与上图类似。而Master负责在合适的byte lanes上采集数据。

3、只有当Slave 的response为OKAY的时候才需要提供valid的data,当response为SPLIT、ERROR和RETRY的时候是不需要提供data的。

大小端规则(Endianness)

所有的module、data和bridge都必须拥有相同的大小端规则

AMBA不支持动态调整大小端规则

对于模块设计而言,只有那些需要应用在多场景下的模块需要被设计成双端模式,通过某个配置pin脚或内部控制bit来选择大
端模式还是小端模式。对于大多数专用的block,固定的大单模式或小端模式都会导致接口更小、功耗更低且性能更佳。

Arbitration(仲裁)

AMBA使用仲裁机制来确定当前只有一个Master获取了总线的控制权

arbiter不仅仅要接受来自Master的request信号,根据优先级算法来确定谁获取总线的控制权;也需要接受来自Slave的request信号,用以确定Slave要已经准备完成之前被SPLIT的transfer,从而将某个Master的request给unmask。

两种情况下Slave会和Aibiter产生互动
1、Slave支持Split response
2、Slave需要检测当bus的控制权改变时burst是否完成了所有的transfer

arbiter signals

HBUSREQx:

由每个Master驱动,用于向arbiter来要求总线的控制权。(AHB系统中最多可以有16个Master,则此信号最多 有16条)。

HLOCKx:

由每个Master来驱动,与HBUSREQx具有相同的时序,用于向Arbiter指出Master请求的一个burst中的多个transfers是不可以分开传输的。一旦arbiter grante了此Master的请求,在此Master的burst传输完毕之前,不能改变总线控制权。

HLOCKx信号线必须比ADDR信号至少提前一个cycle有效。

HMASTER[3:0]:

由arbiter来驱动,表示当前哪个Master拿到了bus的控制权。同时当Slave具备SPLIT功能时,Slave也可以根据HMASTER来确定对哪个Master执行SPLIT。之后通过arbiter恢复哪个Master的优先级。

HMASTLOCK:

由arbiter来驱动,用于表示当前的传输是否为locked sequence。这个信号与地址和控制信号具备相同的时序(即当burst开始时,address和control被驱动,此时arbiter也确定了当前的 sequence是否为locked,进而将HMASTLOCK assert或deassert)

HSPLIT[15:0]:

由Slave来驱动,表示当前的那个Master被处于SPLIT的状态。

requesting bus access

通常情况下,只有当上一个Master的所有transfer都传输完毕的时候,arbiter才会将bus给另一个请求的Master。但是在某些特殊情况下,arbiter也可以提前结束某个未完成的burst,然后将bus给另外一个具有更高优先级的Master。

对于固定长度的burst,Master只需要请求一次,然后arbiter grant之后,会根据HBURST的类型来确定需要传递的beats数量
当前burst传递完毕后,需要再次发起request才能获得总线控制权。

对于非定长度的burst,Master必须持续请求,直至最后一个transfer已经开始。

如果Master在burst中途失去了总线控制权,则它必须再次发起requeset来获得总线

当没有总线请求时,arbiter会将总线控制权赋予default Master,此时这个Master必须要发送IDLE类型的数据,此数据会被Slave忽略

Granting bus access

当arbiter根据内部的优先级算法确定了最高优先级的Master之后,若要将bus给予某个Master,则将该Master的HGRANTx信号asserted就可以。

当current transfer完成时(标志为HREADY的高电平),此时新的Master就会通过HGRANTx来获取总线控制权,下一时刻,HMASTER[3:0]也改变,用于表示新的Master的Master number

T1时刻之后MasterX发起了request,中间过了很长时间,在T3时刻之后,arbiter赋予了masterx的bus控制权(此时肯定是处于HREADY的高电平)。T4时刻后,aibiter提供了Master的number和请求时给的控制信息,T5时刻后,在T6时间到来之前将data放在WDATA上给Slave采样。

T3 Grant之后,由于HREADY为低电平,因此wait了一个cycle才发出ADDR和control signal。发出后由因为HREADY为低电平,因此又wait了一个cycle才发出data。发出data后由于wait了一个cycle,Master的data也另外保持了一个cycle才被Slave采样。

当burst的最后一个HADDR被送出时,grantx信号的控制权也同时发生改变。例如从grant1改为了grant2。但是此时HADDR的控制权还在Master1手里(【重点】grantx是在最后一个addr被采样的时候被采样的,即二者同时被采样)

下一个cycle(无wait时):HADDR控制权移交,data bus发出最后一个data。此时data bus的控制权还在Master1手里,但是HADDR的控制权已经在Master2的手里了。

下一个cycle(无wait时):HDATA bus的控制权移交。

因此data bus的控制权实际上比addr bus的控制权晚一些,会有一个相对延迟

【注意】这里认为Decoder指的是arbiter内部的decoder,而不是与Slave连接的Decoder。

由于采用中心式的multiplex,Master可以在任何时候发去request,HGRANT只是被用来提醒Master他什么时候获得的总线控制权,从而判断什么时候slave会采样到address信号。

Early burst termination

当arbiter判定当前的burst必须提前结束给另一个Master,以此来避免延迟的话,当前的burst会被提前结束。

如果一个Master在burst中途失去了bus的控制权,则Master必须re-arbitrate来完成剩下的burst。Master必须保证HBURST和HTRANS信号必须合法,例如:如果一个8-beats的burst在完成了3个transfer之后失去了总线的控制权,则之后再次获得bus之后,可以使用5-beats的undefined length burst或4-beats fixed length bust紧接一个single-beat undefined length burst。

Locked transfers

当arbiter grant了一个请求了HLOCK的Master之后,它必须保证其完成burst的所有transfer之后才能释放总线给其他Master

在locked sequence之后,aibiter会将master的grant信号延长一个transfer,确保最后一个transfer可以成功完成,没有收到SPLIT货RETRY的response

(之前的情况是上一个master的最后一个address发送完同时,grantx信号的控制权已经改变。下一个cycle改变Master addr bus的控制权,此时还有最后一个transfer的数据没发送完)

因此推荐但不强制,在locked sequence之后嵌入一个transfer的IDLE状态。(则 在IDLE状态开始时grant信号交换控制权,而非在最后一个addr开始时交换grant信号控制权),插入的IDLE状态可以让最后一个数据在IDLE内传输完毕。下一时刻,data bus和addr bus同时交换控制权。

default Master:

每个系统都必须包含一个default master

这里分两种情况:
1、所有的master都没办法使用总线时(如所有的Master都在等待SPLIT transfer完成时),arbiter将总线给予default master
2、没有master对总线发起请求时,arbiter将总线给予default master或给予从低总线访问延迟中获益最多的master

当系统将总线赋予default master时,default master只能使用IDLE transfers

Split transfers

SPLIT transfer将master提供地址的操作和slave利用data response的操作分开来,从而提高了总线的总体利用率。

当slave认为这次transfer需要花费很长的时间时,它将通过SPLIT response来告诉arbiter,此时arbiter将mask掉slave所指的master,不给它bus的控制权,直到arbiter检测到slave已经准备好了的信号

给与SPLIT response的Slave意味着它可以完成这个transfer,只是现在不行。它通过HMASTER[3:0]来判别Master的。

当Slave觉得自己准备好了的时候,它根据之前记录的HMASTER[3:0]来发出对应的HSPLITx给arbiter,而arbiter每个cycle都在检测HSPLITx的值。arbiter检测到对应的SPLITx之后,将对应的Master给unmask掉。

对于每个支持SPLIT的Slave来说,它针对每个Master的HSPLITx可以全体求或,构成HSPLIT总线,由于一个系统中最大有16个Master,则建议所有支持SPLIT的Slave必须支持16个Master,Slave的HSPLIT总线宽度为16

SPLIT transfer sequence

1、Master发出HADDR和control signals

2、如果Slave能够立刻提供数据,则就提供了。如果不能,则回复SPLIT response,同时还必须记录当前的HADDR[3:0]

3、如果arbiter grant了其他的Master,则产生bus控制权handover。如果所有的Master都被SPLIT了,则grant default master

4、当Slave准备好完成transfer时,根据之前记录的HADDR来assert对应的HSPLITx

5、arbiter每个cycle都检测HSPLITx,检测到HSPLITx asserted之后。arbiter恢复了对应Master的优先级

6、当此Master重新request时,arbiter最终会grant。

7、当transfers最终完成时,Slave回复了OKAY response

Multiple split transfers

AMBA协议规定每个Master仅允许有一个未完成的传输(outstanding transcation)。

如果某个Master需要支持多个outstanding transcation,那么它需要对每个outstanding transcation配备单独的request和grant信号,在protocol level这个单独的模块就像多个Master一样。

但是Slave却可以同时将多个Master处于SPLIT状态,Slave不需要记录Master的address和control信息,只需要记录master number。

Master发起一次burst传输,在完成所有的Slave传输过程中,可能会多次被Split打断,也有可能被多次赋予总线控制权

Preventing deadlock

single trasnfer永远不会引起 AHB的lock,因为slave必须被设计得能够在一个实现规定大小的cycles范围内完成transfer。

(【理解】这里理解为Slave对单个transfer能被延迟的大小确定了上限,之前有提到过,不超过16来着。,每个slave不要插入超过16个 wait state,以免单个Slave长时间占用总线)

当多个Master都试图去访问某Salve,但是Slave回复了SPLIT或RETRY,但是在一定程度上Slave本身根本处理不了这个response,则就会死循环。(例如这两个Master要的数据是以对方得到数据为前提的)相当于Master一直在询问,而Slave一直让它等着。无外力作用的情况下,就会陷入deadlock

split transfer造成的deadlock

通过让Slave支持最大16个Master withstand来解决deadlock的问题,让所有的Master都等待,处于Low priority 的时候,slave就可以有序地(in an orderly manner)处理所有的request了,从而指示aibiter先处理哪个request,从而确保了所有的request都能够最终完成service。(其实不太能理解这个避免deadlock的方案

当Slave有多个outstanding request的时候,它可能会以任何顺序来处理这些请求,虽然slave应该意识到locked transfer应该在其他transfer开始之前执行

retry transfer造成的deadlock

一个回复了RETRY的Slave在同一时间只能被一个Master访问,这并不是bus协议内容,而是系统架构中应当保证的

总线协议中对它的唯一要求是:slave必须在提前一个predetermined 时钟周期将HREADY拉高

在那些支持RETRY的slave内部,需要提供一个硬件保护机制。在RETRY期间查询每个试图连接slave的master,看它的master number是不是与之前回复RETRY的的时候一致,从而确定是不是相同的Master。如果相同,则开始transfer;如果不是,则可以采取如下替代措施:

Bus handover with split transfers

协议要求Master在收到SPLIT或者RETRY之后立即加入一个IDLE transfer,从而允许总线被移交给另外一个Master。

【理解】这个地方的意思是,因为SPLIT和RETRY都是2-cycle response,因此在2-cycle的第一个cycle结束后,Master已经知道了Slave的response

在第二个Cycle内,grant信号被立即释放,向HTRAN输入IDLE来确保2-cycle response的第二个Cycle完成。同时也保证了另外一个Master的grant信号在Address的前一个Cycle 被asserted。

【对比】之前的lock sequence完成之后,transfer被延长了一个Cycle,此时建议加入一个IDLE,但是不是强制;而这儿为了完成2-cycle response,IDLE是强制必须加入的。

Reset:

HRESETn是AMBA协议中唯一一个低电平有效的信号,是所有bus的基本复位信号。

reset信号采用的异步复位和HCLK上升沿同步释放的操作

在reset期间,所有的master必须保证其address和control signals在valid levels,而让HTRANS处于IDLE。

AHB data bus width

在不增加运行频率的情况下增加系统带宽的方法之一是增加片上总线的宽度。随着PCB层数的增加和大容量内存单元的使用,都要求更宽的片上总线。

AMBA协议允许的数据总线宽度为8、16、32、64、128、256、512和1024,但是建议使用的最小总线宽度为32bit,最大总线宽度为256bit

无论对于读还是写的transfer,模块都必须从对应的byte lane上去采样获取信号(根据大小端规则来确定),而不是直接将所有的byte lane上的数据都复制过来。

narrow slave on a wider bus(Slave上的总线宽度比Master窄)

上图显示的是原本设计的32bit总线宽度的Slave要被连接到64bit 总线上去,只需要增加一些额外的外部逻辑,而不用修改内部结构。

数据输入

此时能够通信的条件是Master和Slave都约定要以HSIZE等于32来通信,只是物理总线宽度不一致。HSIZE为32bit,则根据地址对齐的原则,传输地址位的低两位为00,当HADDR[2]=0时,则表示64bit bus的Master要在低32bit bus上传送数据了(小端传输),Q低电平,HWDATA[31:0]进入;当HADDR[2]=1时,表示Master要在高32bit bus上传输32bit数据了,此时Q高电平,HWDATA[63:32]进入;则保证虽然物理上总线宽度不一致,但是实际上二者实现了32bit的数据传输

数据输出

输出地方有两种方案:
1、将32bit的数据直接驱动在64bit bus上,31:0和63::3都被RDATA[31:0]驱动
2、利用一个额外的逻辑电路确保同一时刻只有一个64bit总线上的一半发生电平变化,从而降低功耗

Slave只能接受与其物理总线宽度相同的transfer,如果Master试图使用更宽的transfer,则Slave可以报ERROR。

【理解】上面这句话的意思是,如果Slave的data bus 为32bit,则虽然可以通过外部逻辑电路连接至64bit的bus上,但是HSIZE不能超过32bit,超过了的话,一个transfer就要超过32bit的bus,而tranfer是最小单位,无法再分开,则Slave就无法执行。

wide slave on a narrow bus(Slave上的总线宽度比Master宽)

上图显示的是原本设计的64bit data bus的Slave被连接至32bit的总线上

数据输入

参考上一个图,输入的地方也有两种方案

1、直接将数据的32bit数据赋值给64bit的全部,相当于每一bit赋值两次

2、通过一个额外的逻辑电路确保同一时刻只有一个64bit总线上的一半发生电平变化,从而降低功耗

数据输出

此时还是约定Master和Slave都以32bit的data来传输
1、当HADDR[2]为0时表示Slave将从64bit bus的低32bit来传输
2、当HADDR[2]为1时表示Slave将从64bit bus的高32bit来传输

从而将64bit的数据分时得放在了输出的32bit bus上。
Q用于区分时间段,分别将[63:32]和[31:0]连接到HRDATA[31:0]

Master

bus master可以轻易调整以适应更宽的总线结构,主要通过以下方式:

1、复用输入总线(根据大小端规则,利用Master data bus分时检测AHB common bus的部分总线)

2、复制输出总线(将master的bus输出按倍数扩展,以适应AHB common bus的总线要求)

但是bus Master不能适应比它更窄的总线(这里的总线宽度指的是所有的AHB总线宽度,相当于所有Master和Slave都挂载的那条公共bus,而非从每个Slave或Master连接至公共bus的interface)

因为Master根据HSIZE的要求,要求传输与master 的data bus宽度相同的HSIZE。此时宽度为HSIZE的数据会在一个transfer内全部加载在Master的data bus上,AHB总线的bus宽度小于Master的bus宽度,不可能在一个transfer内采样完毕,因此会出错。

因此这种情况下,除非有内部结构可以限制Master的HSIZE的大小,让它不能超过AHB bus的宽度,这样就能运行。

Master不应该传输宽度超过它所连接的data bus总线宽度的HSIZE。

【举例说明】

AHB 总线bus为64bit,若Master1的data bus宽度为32bit。HSIZE设定为32bit。则Master的输出会一次性占满32bit data interface,为了适应AHB总线,将Master的输出复制一遍,然后赋值给AHB总线;对于输入,在AHB总线上的data会分时分布在0-31bit和32-63bit,只要Master的0-31bit分时去采样就行了。

AHB 总线bus为32bit,若Master1的data bus宽度为64bit。HSIZE设定为32bit,此时自然不会有什么问题,输出复用,输入复制就可以实现。但是对Master来说,它完全有理由设定HSIZE 为64bit,逻辑上完全行得通。但是此时需要一次性同时将所有的64bit的数据都放在bus上,AHB总线只有一个transfer的时间来采样,AHB总线只有32bit,无法实现。

因此,Master不应该传输宽度超过它所连接的data bus总线宽度的HSIZE。

AHB AMBA components

AHB bus slave

AHB bus master

AHB arbiter

AHB decoder

第四章  AMBA ASB

第五章  AMBA APB

APB总线结构用于低功耗和接口较简单的场合。一般用于那些低带宽、性能要求不高的外设。

latch:锁存的意思,即此时Bridge 锁存了来自Master的address和control signals,然后指导APB总线上的外设来进行操作。

之前在AHB总线中的时候也提到过latch,当时是在SPLIT transfer中提到的,但是当时说的是在SPLIT transfer的过程中,如果Slave response了SPLIT,则此时Slave并不会latch当前Master的Address和control signals,只是记录HMASTER的number,方便之后告诉arbiter可以重新开始Split的传输。

APB STATE

一共分为三个状态,state

1、IDLE:此时PSELx:PENABLE = 1:0,外设总线的default state

2、SETUP:此时PSELx:PENABLE = 1:0,当transfer开始时,bus转至SETUP state。外设只在SETUP state呆一个时钟周期,等到下一个周期的上升沿就转至ENABLE state

3、ENABLE:此时PSELx:PENABLE = 1:1,当从setup state 转换至enable state的时候,地址信号,写信号和片选信号都必须保持不变ENABLE状态下也仅仅持续一个时钟周期,此时如果没有transfer request的话,就转回IDLE状态,如果有的话,就直接转至SETUP状态。从ENABLE状态转至SETUP状态的过程中,允许地址信号、写信号和片选信号出现一些小错误glitch

write transfer

在图中的T2时刻之前,APB Bridge就已经latch到了来自Master的HADDR和HWRITE,此时在外设的上升沿T2将PADDR、PWRITE、PSEL和PENABLE等信号驱动在Slave上。

由于此时是write transfer,HWDATA在T2时刻之前也已经latch了,则在T2时刻PDATA也被加载在数据线上。

如果在T4时刻有下一个transfer要开始,则T4之后不会转到IDLE,而是直接转至SETUP state

为了减小功耗,在一次transfer完成之后,address信号和write信号并不会改变,直到下一次transfer需要改变的时候再变。

APB协议仅仅要求了在两次transfer之间enable信号要准确变化,因为在back to back transfer(读 transfer后接一个写transfer,再接一个读transfer,以此类推)的时候,select信号和write信号可能会产生glitch(小故障,毛刺)。

read transfer

在图中的T2时刻之前,APB Bridge就已经latch到了来自Master的HADDR和HWRITE,此时在外设的上升沿T2将PADDR、PWRITE、PSEL和PENABLE等信号驱动在Slave上。

由于此时是read transfer,Slave只有在T3时刻才知道Master想干嘛,因此T3时刻之后,即ENABEL state之后将会read data加载在PRDATA线上,只持续一个Cycle。

在T4的上升沿,数据被Bridge采样,之后传输至Master

APB AMBA components

APB bridge

APB Bridge是APB总线上的唯一一个Master,也是更高一级系统总线(AHB或ASB)中的Slave。

APB Bridge主要完成以下功能:

1、latch地址信号,并且在整个transfer期间保持其有效

2、解码地址信号并产生外设片选信号PSELx,在一次transfer期间,只有一个PSELx是有效的

有一个问题,这个地方解码的地址信号是哪个信号?HADDR?还是其他的从HDATA中来解码地址,及核心问题:PSELx是怎么产生的?)回答:是解析HADDR信号,因为实际上各个外设都是映射在memory map里面的,解析HADDR就可以知道对应的addr属于哪个外设的内存空间,进而将对应外设的PSELx给asserted

3、将wdata驱动在APB总线上用于write transfer

4、将APB总线上的data驱动到高层级系统总线上用于read transfer

5、产生timing strobe, PENABLE信号,用于transfer。

APB Slave

APB总线的具体接口可以根据设计风格和设计需求来灵活配置

write transfer

来自Master的WDATA可以在以下时间被latch:

1、当PSEL为高电平时,在PCLK的上升沿采样(即在SETUP结束时或ENABLE结束时Slave采样数据)

2、当PSEL为高电平时,在PENABLE的上升沿采样(即在enable开始时Slave采样数据)

read transfer

read transfer的时候,Slave在ENABALE阶段,将data的数据放在PDATA数据线上。根据PADDR来确定应该读哪个寄存器。

APB与AHB之间的交互

read transfer

可以认为PRADA和HRDATA是连接起来的,因为二者的data是同时改变的。由上面可以看出一个read 的transfer至少包含了3个cycle

与外设之间的通信,Master在送出ADDR之后必须要wait一个时钟周期,让setup 和enable之间变换。

如果遇到非常高频情况,需要APB Bridge做一级数据缓存。即在T4时刻由register采样来自APB Slave的data,下一个时刻再驱动至AHB总线的HRDATA线上。则此时Master就要等2个时钟周期了。尽管这需要额外一个cycle的wait,但是这可以让AHB总线运行在更高的频率上,从而总体上提升系统性能。

read burst transfer

write transfer

由上图可以看出,在一个write transfer里面,从Master发出地址,到最后接收到数据,最少需要4个Cycle

write burst transfer

第一个 transfer在完成时是不需要wait的,之后的transfer完成时,后面都需要有一个wait

一般来说Bridge上需要两个地址寄存器,一个用于sample下一个address,一个用于保持当前transfer的地址。

back to back transfer

按之前的读写顺序,T4-T5时间段内,HREADY为高电平。在T5时间,addr1的使命就已经完成,Bridge可以采样addr3的地址。T5-T6时间段,DATA3就可以进入了,从而在T6时间被Bridge采样。
1、但是实际上,如果真的这样做的话,则T6时间,Slave采集到了address和Data3,则此时PWRITE就必须为write,且此时应该为write 的setup进程。但不幸的是,此时slave处于read状态,且为enable进程。互相矛盾,因此,不能选择如上的操作过程
2、若T5-T6时间段HREADY为高电平,此时ADDR4也就必须从T6时刻进入,data3也从T6时刻进入,则bridge在T7时刻必须同时采样data2和data3,但实际上并没有这么做,可能是会产生亚稳态或者硬件错误之类的吧(或者还有问题就是Bridge用于存储data的寄存器有几个?是rdata和wdata分开?还是二者公用一个?
3、因此最后的结果是将一个读写过程看做一个周期,中间Slave会经历一次IDLE state。要求读写之后Master wait3个cycle,就按照它说的办

正常的read pipeline中,读只等一个cycle
正常的wirte pipeline中,写只等一个cycle
这里理解为只有当HREADY为高电平时,bridge才会采样HADDR和HWRITE
HWRITE在下一个cycle就必须映射到bridge中去,只有一个寄存器位置,而HADDR有两个

tristate data bus

推荐AMBA APB总线上read data bus和write data bus 分开,这样就可以使用复用或求或的方式来与APB总线上的Slave来进行交互。如果使用tristate(三态)总线的话,则读数据和写数据就永远无法同时进行了。

如果一个三态的数据总线在read burst的setup cycle,或当总线处于IDLE的时候,当不同的driver去驱动总线的时候,都需要一个clock cycle来做turnaround。对于三态总线的write burst transfer来说,不需要turnaround因为每次transfer的时候的setup cycle,bridge都会将数据驱动在数据线上。(因此data的方向都是在rread transfer的setup阶段和IDLE阶段来执行的。)

如T3时知道下一个为read transfer,则在T5开始后,进行turnaround,将原本的write转为read

如T7是知道下一个为write,则中间正好有一个IDLE,用于做turnaround,将原本的read转为write。(之前强行在back to back的加入3个wait,而不是2个,是不是也是因为要给出IDLE,在write transfer到来之前turnaround,而在write transfer内部,无法实现turnaround的操作。)

Interfacing rev D APB peripherals to rev 2.0 APB

当外设设计时使用的原本D APB 来设计的,要想能正常使用,建议使用符合AMBA 2.0协议的APB bridge,然后将APB Slave做一些修改,使其能够满足AMBA APB 2.0的协议标准。

APB 2.0和rev D之间的区别

快速区别一个APB外设是按照rev D还是rev2.0设计的

含有PSTB input端口的就是rev D,含有PENABLE input端口的就是rev 2.0

第六章  AMBA测试方法学

数字IC设计----AMBA总线协议(来自英文原版)相关推荐

  1. 数字IC设计--------AMBA AXI协议(英文原版)

    AXI:AMBA Advanced eXtensible Interface (AXI) Protocol Specification 目录 chapter 1 Introduction about ...

  2. 数字ic设计——AMBA总线(1)AMBA总线介绍

    AMBA总线介绍 AMBA(Advanced Microcontroller Bus Architecture) 总线是由ARM公司提出的一种开放性的片上总线标准,它独立于处理器和工艺技术,具有高速度 ...

  3. 数字IC设计入门篇:APB总线协议学习心得

    声明:本文章是本人学习AMBA  APB协议的一些个人理解,仅用于学习交流之用.本人学习APB协议时参考的是ARM公司官方的APB协议技术规范文档(编号:IHI0024D).受限于本人的知识水平,本文 ...

  4. 数字IC验证:ARM协议之AMBA低功耗接口Q-channel

    写在前面: 最近实习项目里用到Q-channel,因此简单整理一下,内容大多来自ARM官方文档与网络上的,我主要做一个整合,加上自己的理解补充,内容来源都会分别标出.如有侵权请指出,立刻删帖. 官方文 ...

  5. 数字IC验证:总线握手协议(VALID/READY握手机制)

    写在前面: 最近学习总线协议,涉及握手,因此整理本文.若内容有疑惑或错误之处,请在评论区指出,感谢! 文章目录 1 什么是"握手"? 2 VALID/READY握手机制 3 Cas ...

  6. IC设计前后端常用的英文术语

    英文缩写 英文全称 ADC-Analog to Digital Convert>>>模拟信号到数字信号的转换电路 AHB-Advanced High Performance Bus& ...

  7. 数字IC设计SOC入门进阶

    声明:本系列文章全部来自网络公开资料整理,并在文后附上网页链接.仅用于学习交流. 前言 硕士毕业从事FPGA逻辑开发已N年,对于未来的发展方向.技术提升等充满了困惑.迷茫.此时,恰逢数字IC设计岗位兴 ...

  8. linux mipi驱动分析_寒武纪社招内推数字IC设计、DSI驱动、软件架构、产品经理、芯片架构、工具链开发、深度学习、FAE工程师...

    点击上方蓝字关注我吧! 为什么内推更靠谱?内推是基于人脉关系链的推荐,其背后有一定的信用背书,靠谱的人推荐的人相对也会比较靠谱,所以企业一般职位都是从内部开始分享的,相较于自己海投简历,内推的效率和成 ...

  9. 起点篇:跨入半导体行业,数字IC设计

    起点篇:跨入半导体行业,数字IC设计 机缘巧合跨入IC行业 前言(忽略)   2019年是我大学的完结,也是我读书生涯的完结.因为上大学时,并没有考研的想法,而且虚度了2年多的大学时光,每天都大把时间 ...

最新文章

  1. 2019第四周作业(基础作业+挑战作业)
  2. 驭龙HIDS安装及测试
  3. Java并发编程之:Vector和ArrayList的区别
  4. 让PIP源使用国内镜像,提升下载速度和安装成功率。
  5. django定义模型类-14
  6. 关于.NET5在IIS中部署的几个问题总结
  7. MySQL存储过程中游标使用
  8. css3 border
  9. XAF框架简介-C#语言
  10. JZOJ5371 组合数问题
  11. URI和URL的区别与联系
  12. SSM期末复习题(仅供参考)
  13. 对比修改过的两个BOM表
  14. 高通下载模式9008
  15. 使用IAR下载烧录调试
  16. Impala集群搭建报错,主节点启动成功,但是worker节点的impalad启动失败
  17. 版权符号©的输入方法
  18. 进阶无人驾驶—百度Apollo高精度地图
  19. rockchip的调试手段
  20. Camera Shading介绍

热门文章

  1. 2021智能营销领域最具商业合作价值企业盘点
  2. 电商直播的带货技巧有哪些?
  3. Android 天气APP(三十二)快捷切换常用城市
  4. html小米左侧导航栏,小米PC导航栏下拉.html
  5. 解决SolidWorks建模3D打印圆柱体不圆圆柱体多边形圆柱体有棱角的问题
  6. 新浪、腾讯股票价格相关接口
  7. 市场调研公司欧睿国际揭晓描绘中国城市千禧一代和Z世代的8个消费趋势
  8. windows剪切板的历史记录
  9. 移动审批工作流设计与实现
  10. js 设置html标签样式表,js怎么设置css样式?