一、APB协议
APB总线针对低功耗外设应用,为减小功耗和降低接口复杂度作了优化,可以与其他系统总线相连。
在SOC设计中,APB一般作为IP的配置接口,包括低速IP如I2C,UART等,也包括DDR, PCIe, Ethernet等高速IP,可以方便的实现CPU对外设IP的寄存器配置。系统中一般会实现一个AXI2APB或者AHB2APB的转换桥将APB口挂载在系统上。一个AMBA APB设计通常使用APB桥接器连接至主存储器系统,对于APB来说,可以将Bridge看作是发起操作的master。
1.APB基本传输
总线状态机的状态跳转如上图。
不管是写入还是读出,只需记得以下两点:
- PSEL=1, PENABLE=0时,采样commond
- PSEL=1, PENABLE=1时,采样data
write_transfer
写操作,指master数据放入总线,slave读。
APB总线是不要求performence的,所以是寄存器输出类型,输出会比控制信号晚一个时钟周期。如果必须要在当前周期输出,则必须用assign输出类型。T1上升沿,Addr与Data一起被drive进来,T2上升沿时刻,PSEL=1,PENABLE=0(SETUP状态)采样control信号,包括PADDR和PWRITE等。T3上升沿,PSEL=1,PENABLE=1(ACCESS状态)采样data。
含有等待状态的写传输,PREADY信号拉低,对应上升沿的时钟周期无效。PREADY可以拉低来延长读写操作的周期数,一般由slave给出。
read transfer
读传输是slave写,master来读。slave采样commond后将数据放入。PRDATA可以认为是slave向master传输数据的数据总线。写的时候数据和地址是一同放入的,master发出的数据一定是这两个数据都准备好的情况,只是看对应地址的slave能不能接受这笔数据,接不了就PREADY拉低。
而master接受数据也就是读的情况,master知道地址是哪个,但是要拿到的data是啥,什么时候准备好,一概不知,这些信息是slave知道的,slave什么时候准备好,就什么时候拉高PREADY。
Synopsys apb vip波形解读
write:
黄线标出的上升沿处,PSEL=1,PENABLE=0,采样cmd信号,PADDR为2f76_dbf8,PWRITE为高,写操作。下一个时钟上升沿,PSEL=1,PENABLE=1,采样data。
read:
二、AHB协议
APB协议是一个master多个slave,AHB则是多个master多个slave。
AHB协议中比较重要的一点就是总线仲裁,所有的master在发送东西之前都要经过Arbiter的仲裁。
1.AHB组件
master | 有权启动读/写操作,并提供地址和控制信息,任何时刻,总线上只允许一个主设备处于活动状态。 |
slave | 在给定的地址空间范围内相应读写操作,并返回给活动的主设备成功,失败或等待数据传输的信号。 |
Arbiter | 保证任何时刻总线上只允许一个主设备发起数据传输,一个AHB总线上只能有一个仲裁器。 |
Decoder | 解码每次传输的地址信息,并对相应的从设备提供选择信号,所有的AHB总线都需要一个单独的中央解码器。 |
大致是这个样子的
Decoder会解码master在总线上传输的address,告诉mux应该放哪一个slave的信号出去,根据地址解码确定slave。Decoder中还有HSELx信号连接到每个从机,每个AHB从机都有自己独立的从机选择信号,用该信号来表示当前传输是否打算送给选中的从机。
2.数据传输
区别于APB协议的一点是,AHB的数据传输是pipeline类型的。
AHB协议中定义了4/8/16节拍的突发传输,不定长突发传输以及单词传输,支持INCR与WRAP。
INCR是递增突发传输,WRAP是卷绕突发类型。
INCR传输,地址就是前一个地址的等量递增。WRAP传输,如果突发起始地址没有与突发传输总字节数对齐,那么当传输至地址下界时,传输地址将卷绕会地址上界。
INCR4传输:
WRAP4传输:
两种传输对比,在同样的起始地址下,结束地址却不相同,这就是卷绕与递增的不同了。
对于卷绕来说,对波形的解读,需要判断的是传输的总字节数以及传输的起始地址。
用上图为例,4节拍的,大小为4个Byte,传输总字节数为16个Byte。
所谓地址边界就是若某地址能够被一整数除尽,该地址就称为整数对应的地址边界。
初始地址如果是0×34,显然是没有对齐的,地址是十六进制的,所以只需要看最低位能不能整除16即可,显然是0余4,边界不对齐。这样的情况下就列出地址边界变化,16Byte对应的地址边界变化为:
0×00=>0×10=>0×20=>0×30=>0×40......等等
所以初始地址为38,3C后下一个地址是40,在此传输为地址下界,需卷绕回地址上界0×30。其他WRAP的分析方法也都相同。
传输类型
00 IDLE:当总线主设备获得总线却不需要执行总线传输时,使用IDLE信号,从设备必须返回一个零等待状态的OKAY相应。即没有master需要传输东西。
01 BUSY:主设备正持续处于突发过程,但下一个传输还没有立即开始,此时的地址和控制信号会影响突发过程的下一个传输。即总线被master占领,且当前cycle无东西。
10 NONSEQ:表示突发传输的第一个传输周期或者单次传输,地址和控制信号与前一个传输周期无关。代表突发传输的起始。
11 SEQ:突发传输的剩余传输周期都是SEQ类型,地址和前一个传输周期有关,控制信号与前一个传输周期相同。
突发传输的起始地址一定是NONSEQ类型,而剩余传输周期一定是SEQ类型的。
3.Synopsys AHB VIP波形解读
将Synopsys ahb vip中transaction中8种传输类型权重设为相等,并运行random_wr_rd_test,其结果如下。
HBURST显示各个突发传输类型都已存在,挑几个来读一下。
WRAP16:
HBURST为6,是WRAP16,size为1个Byte,所以传输总字节数为16个Byte。所以地址边界为
0×00=>0×10=>0×20=>0×30=>0×40=>0×50....
起始地址为e17_fc28,一直到 e17_fc2f,下一个就是地址下界e17_fc30了,所以应该卷绕回地址上界e17_fc20,所以根据卷绕突发的特点,e17_fc2f后续的地址变化应该是:
e17_fc20=>e17_fc21=>e17_fc22=>e17_fc23=>e17_fc24=>e17_fc25=>e17_fc26=>e17_fc27。
后续的波形如图
再读一个INCR16的,看一下两个的区别。
HBURST为7,size为1个Byte,起始地址为11e7_9581。
地址一直增加到11e7_958f,到地址下界11e7_9590时并没有卷绕,而是直接进行递增。
再读一个INCR
INCR为不定长递增突发,读波形图一定注意,HTRANS为2的NONSEQ才是一次突发传输的起始, 上图中的INCR传输一共发送了28个数据。除了第一个NONSEQ外,突发传输的剩余过程都是都是HTRANS为3的SEQ类型。
再读一个INCR4
HBURST为3,突发传输类型为INCR4。size为1个Byte,地址由49b1_9851一直递增到49b1_9854,传输的起始为NONSEQ,剩余传输为SEQ。
再读一个WRAP4
HBURST为2,代表其突发类型为WRAP4,起始地址为4855_29ea。size为2个Byte,传输总字节数为4Beats×2Byte=8Byte,地址边界变化为0×00=>0×08=>0×10=>0×18=>0×20.....等等。图中地址变化到4855_29ee时,处于e8到f0之间,INCR4情况下下一地址应该是4855_29f0,此地址属于地址下界,应卷绕回地址上界也就是e8,所以WRAP4的下一个地址应为4855_29e8。
此地址边界的表现应该是
地址是存储空间的门牌,空间内存了东西才能是写入了该地址,f0的空间并没有写入东西,而是直接卷绕回e8,是e8的空间内写入了数据。
再读个INCR8。
8节拍递增传输。size是4个Byte,传输总字节数为8Beats×4Byte=32Byte。
波形太长,不截了吧。INCR4/8/16其实没啥好说的,根据HTRANS去判断传输的起始,知道起始地址后根据相应size大小将地址递增即可。
再看一个WRAP8,找一个size是4个Byte的,前面接一个SINGLE传输。
SINGLE,地址为6000_5110, HTRANS为2,前面说过NONSEQ可以代表单次传输。
WPAP8传输的起始地址为66e5_6f14,size为4个Byte,所以传输的总字节数为8Beats×4Byte为32个Byte。所以地址边界变化为
0×00=>0×20=>0×40=>0×80......等等。
地址66e5_6f1c后卷绕回66e5_6f00。
行,不看了。
master与arbiter:
HBUSREQx:信号源master,主设备x用该信号向总线仲裁器请求获取总线,系统中每一个总线主设备都具有一个HBUSREQx信号。
HLOCKx:信号源master,该信号为高电平时,说明主设备获取了对总线的访问锁定,其他主设备无法获得总线应答知道HLOCK拉低,即保护总线占有权。
HGRANTx:信号源Arbiter,该信号表示主设备x具有最高优先级,HREADY信号变高时,一次总线传输结束,地址/控制信号所有权改变,HREADY和HDRANTS均为高时,主设备x得到总线访问权。HREADY和HGRANTx均为高时,主设备x得到总线访问权。
HMASTER:仲裁器Arbiter用此信号来提示某个主设备当前正在占用总线。MUX通过HMASTER获知哪个主设备正试图访问总线。
HMASTLOCK:信号源Arbiter,指示当前主设备正在进行一个锁定序列的传输,与HMASTER信号具有相同的时序。
HGRANTx与HBUSREQx为一对master与Arbiter握手信号,master发送HBUSREQx到Arbiter请求获取总线,指示主设备x拥有最高的优先级,HGRANTx从Arbiter返回到master表示握手成功,当前主设备x获得总线访问权。
关于多拍传输的control信号说明:
当A的control被放入后,ready信号拉高且为高时,后续做相应的采样,然后接受下一组B的control信号等等,采样controlB时候应该伴随data A的数据,但READY信号拉低时,意味着B与controlB信号并未送出,所以处于占位状态,后续信号不能够进来,READY信号拉高以后,才能放走controlB,迎接controlC。所以后续信号是否能够放入,是去看前一个信号的READY信号是否有效。类似于红绿灯,绿灯亮时这一波车才能走,下一波车才能进来。红灯亮,这一波车不能走,下一波车自然也就进不来。
系统总线与外设总线:
- 将所有外设挂在系统总线上并不是一个好的实现方法,大量外设会增加总线负载,增加功耗并牺牲性能。
- 当需要进行时序分析时,慢速设备会限制最大性能,许多简单的外设需要地址信号和控制信号锁存,而高速设备需要流水信号,有些外设只需要用选通信号来进行选择和读/写操作,并不需要高速时钟信号。
所以APB一般不会直接挂在CPU上,APB频率低,数据吞吐率低,会把总线长时间挂死。
三、AXI协议
AXI协议是一种面向高性能、高带宽、低延迟的片内总线,是AMBA3.0协议中最重要的部分。
1.特性
AXi协议中引入了通道channel。AXI总线共有五个独立的通道,分别是
- 写地址通道 write address channel; 握手信号: AWVALID,AWREADY
- 写数据通道 write data channel; 握手信号: WVALID,WREADY
- 写响应通道 write response channel;握手信号: BVALID,BREADY
- 读地址通道 read address channel; 握手信号: ARVALID,ARREADY
- 读数据通道 read data channel; 握手信号: RVALID,RREADY
每个通道有各自的握手协议,互不干扰。
因为通道独立,所以AXI协议支持同时读写。理论上N+1个cycle能读2N个数据。
特性1:outstanding
AXI协议的outstanding是由only start address这个特性引出的。
在传输transaction的时候,READY为低的时候是不能进行传输的,如果想办法将READY为低的时间利用起来,就可以大大提升传输效率。这个利用就是将其他transaction拿到这里去传输。这个transaction可以来自此从机,也可以来自其他从机。问题是系统必须知道后面有其他transaction的存在,才有可能将其他transaction提前传输。可以利用only start address进行transaction的一个排队。
将所有transaction在第一个transaction完成之前进行排队,排队的这个feature就叫做outstanding。
具体能排多少由outstanding NUM决定,具体实现就是存储地址的FIFO的大小
比如AHB的传输,一次transaction的传输会被递增的地址占满,对于AHB来说,transaction的传输没有位置给其他transaction的地址,AXI只传输首地址,transaction传输除首地址以外的其他位置就可以加入其他transaction的首地址(排队)。
特性2:out of order乱序 是否支持乱序只与slave有关,与master无关。
由于outstanding导致的乱序叫out of order,是依赖关系。out of ordert是指transaction完成的时间是乱的。乱序传输的核心是ID。因为最新的协议已经取消掉了WID,意味着写通道的写顺序须和地址通道保持一致。对于写操作而言,AXI写顺序主要涉及到的信号为AWID和BID。同样的,相同ID之间要保序,比如发送AWID为1和2的请求,BID为2是可以先回来的,说明AWID为2的写请求已经完成了。
以读传输为例,AXi的读顺序涉及到的信号为ARID和RID,ARID来自主机,RID来自从机。对于主机而言,同一个ARID序号需要按照发送顺序返回读取的值,ID指的就是一个transaction,两个transaction用同一个ID号的情况下,并不能靠ID号来判断哪个是哪个,所以一定要保序,不能乱序。VIP中,读乱序的深度由read_data_reordering_depth来决定,为1时,不允许读乱序。
interleaving
interleaving是out of order乱序的其中一种实现形式,有更小的颗粒度,进一步允许transaction中beats的乱序。同一个transaction的beats要保序,因为ID是相同的。
写interleaving:在AXI4中被弃用,不再支持,允许transaction级别的乱序,但是不再允许beats级别的乱序。要实现写交织,在总线系统设计中需要增加复杂的逻辑,而且容易产生死锁,而且master可以自行规划写数据的顺序,可以达到interleaving一样的效果,且只有在多master,且master写速度不同时,write interleaving才能派上用场,应用场景也不够广泛。
2.通道握手
2.1 channel握手
五个通道都通过相同的VALID/READY双向握手机制来传输每个通道的数据。
只有VALID和READY均为高时才可以正常发送数据。VALID信号一般用来表示什么时候control信号是有效的,而READY信号用来表示什么时候从机准备好采集数据了。
VALID和READY的前后关系,可以分为三种情况:
VALID before READY
VALID信号拉高,表明已发出有效数据,第三条虚线处,READY信号拉高,表明从机准备好进行采样,进行采样,完成握手。
READY before VALID
READY信号拉高,代表从机已准备好,但第二条虚线处VALID未拉高,在第三条虚线处完成握手并实现数据传输。从机在主机发送数据之前就做好了接受的准备,当主机VALID后,采样到VALID为1时就完成了数据传输。
VALID with READY
VALID和READY信号同时拉高,表明数据有效的同时也可以进行采样,第二条虚线处完成握手,采样数据。协议规定:VALID信号一旦拉高,直到READY信号有效握手成功,接受数据,否则不会主动变低。
read address channel handshake
主机在control信号有效时,将ARVALID置为高,为高后,等待从机的ARREADY信号拉高,完成双向握手机制,进行数据传输
read data channel handshake
从机在数据有效时将RVALID置为高,等待主机的RREADY信号拉高,完成握手机制,进行数据传输。
write address channel handshake
主机在control信号有效时,拉高AWVALID,等待从机拉高AWREADY,完成握手机制,进行数据传输。
write data channel handshake
burst传输时,主机在写数据有效时候将WVALID置为高,等待从机拉高WREADY信号,完成握手传输有效数据。
write response channel handshake
从机在数据有效时,将BVALID置为高,等待主机BREADY信号拉高后完成握手,进行数据传输
2.2 约束关系
单个箭头指向的对象可以在起点之前或之后置高。
双个箭头指向的对象只能在起点之后置高。
读约束关系
数据的返回一定要在control信息成功发送之后。所以读操作的约束关系为读数据通道必须等待读地址通道的数据有效传输之后才能进行数据通道的握手操作。
写约束关系
写操作涉及到三个数据通路,可以直接明确的一点是,写响应通道一定要在写数据通道完成握手之后才能尝试去握手。
写数据通道与写地址通道并没有绝对的先后顺序,因为都是master发出的,所以WDATA可以先于control信号出现,但是读数据通道和读地址通道不行,需要有明确的前后顺序,地址一定要在数据之前给出,否则不知道哪个slave发出数据。
3.数据传输
burst type
AXI协议支持不同的burst传输类型
AWBURST[1:0] ARBURST[1:0] | 突发类型 | 描述 |
00 | 固定长度突发(fixed) | 地址固定的突发,访问FIFO类型 |
01 | 递增突发(INCR) | 地址递增的突发,访问正常序列memory |
10 | 卷绕突发(WRAP) | 地址卷绕的突发,在回环边界会卷回一个较低的地址,访问告诉缓存总线 |
- FIXED :固定地址的传输,所有传输都会写在同一个地址中,主要应用在FIFO的传输中。
- INCR : 有固定长度递增和非定长递增,大部分数据传输都是使用这种方式。
- WRAP : 地址回环传输,主要应用在cache操作中,cache是按照cache line进行操作,采用wrap传输可以方便的从内存中取回整个cache line。
Narrow Transfer
窄传输是通过strb信号指定有效传输数据的位宽来实现,针对一些特定的寄存器读写,或者在不同数据位宽的总线传输中会使用窄传输进行操作。
写选通信号WSTRB允许在写数据总线上进行稀疏传输,每个写选通信号对应写数据总线的一个字节。WSTRB[n]代表WDATA[(8×n)+7 : (8×n)]字段有效。
WSTRB[0]代表WDATA[7:0]有效,WSTRB[1]代表WDATA[15:8]有效,以此类推。
Unaligned Transfer
非对齐传输:AHB总线只支持对其传输,AXI协议支持非对齐传输。
AXI的传输是only start address,只传输首地址,后续的就根据首地址和size,burst来决定。
在第一笔数据传输时,如果首地址不是对齐的,那么主机就会在第一笔传输中对数据进行填充,直到填充至地址对齐,然后再用WSTRB信号将之前填充的数据标记为无效,这样之后传输的地址也就都是对齐的了。填充是为了满足传输地址对齐的需求。非对齐传输只要体现在第一笔传输的数据中。
Transfer size为4个Byte,length为4个Transfer。当传输首地址为0×01时,用strb信号指定对应的Byte有效,后面的传输可以按照正常的传输进行。这笔突发传输的第一笔有效数据就只有3Byte,因为第一Byte数据已经被标记为无效。
传输数据
AXI传输数据的方式是 burst+length
基本读burst
在T2上升沿处ARVALID与ARREADY完成握手,采样读数据通道的control信号。
读回数据D(A0)-D(A3),读数据通道分别在T6,T9,T10,T13处完成握手。RLAST信号拉起,代表D(A3)是最后一笔数据。
这张图显示了master如何在slave接受第一个地址后驱动另一个突发地址。这使得slave可以开始处理第二个突发数据与第一次burst突发完成平行。根据RLAST信号,D(A2),D(B1)分别是地址为A的突发和地址为B的突发的最后一笔数据。
基本写burst
T2上升沿AWVALID,AWREADY写地址通道完成握手,采样control信号。
向slave写入D(A0)-D(A3)数据,T9时刻WLAST拉起,代表D(A3)是写入最后一笔数据。并在T10上升沿完成写响应通道的握手,返回OKAY响应。
Synopsys AXI VIP配置
用directed_test来进行测试
outstanding配置
根据axi reference描述
num_outstanding_xact
指定master/slave可以支持的outstanding transaction数量。如果num_outstanding_xact=-1,则不考虑num_outstanding_xact,而是num_read_outstanding_xact以及num_write_outstanding_xact起作用,相当于读写通道各有一个FIFO,读通道的outstanding能力取决于num_read_outstanding_xact,写通道的outstanding能力取决于num_write_outstanding_xact。如果使用num_outstanding_xact,相当于读写通道共用一个FIFO。
系统配置略,一个master一个slave,调用create_sub_cfgs,将数据位宽和ID位宽标明。
AXI VIP中有四个配置类
- svt_axi_system_configuration 系统配置类,包含整个AXI系统的配置信息,用户可以通过此类来指定系统级的配置参数,用户需从环境或测试用例中向系统子环境提供系统配置。系统配置主要指定 1.system component的master/slave component数量。 2.master/slave component的端口配置 3. virtual top level AXI interface。 4.address map。 5.timeout value。
- svt_axi_port_configuration端口配置类 主要包含系统组件中各个AXImaster/slave的配置信息。端口配置类中提供的一些重要信息是 1.master/slave的passive/active模式。2.启动或禁用协议检查 3.启动或禁用端口级覆盖率。4.接口类型(AXI3/AXI4/AXI4 lite/AXI_ACE/等) 5.端口配置包含端口的virtual interface。
- svt_axi_lp_port_configuration端口配置类低功耗略
- svt_axi_interconnect_configuration 互连配置类,包含互连组件的配置信息,有系统配置的句柄,此类中还包含master/slave port的数量的配置信息,以及这些端口的相应配置。
在directed_test中的配置如下,direted_wr_rd_reoeder_sequence中将sequence_length长度通过config_db set为8,发8个。
//master和slave都要支持此配置
cfg.master_cfg[0].num_outstanding_xact = 3;
cfg.slave_cfg[0].num_outstanding_xact = 3;
//num_outstanding_xact设置好后,对应数量的transaction会在第一个transaction完成之前排好队(outstanding)
初始波形
将num_outstanding_xact改为6,其波形变化如下
在第一个transaction完成前,0~5 transaction已经完成了排队。
out of order
进行如下设置
//slave中可重新排列的待处理响应数为;按顺序处理所有transaction的slave的write_resp_reordering_depth为1
cfg.slave_cfg[0].write_resp_reordering_depth= 6;
//设置master_cfg不允许写interleave
cfg.master_cfg[0].write_data_interleave_depth = 1;
//设置排序算法reordering_algorithm,用于指定对transaction或response进行重新排序的重新排序算法
//仅适用于active slave处理READ数据和WRITE resp transaction
//RANDOM:transaction将以任意随机顺序处理
//PRIORITIZED:transaction将按照优先顺序处理
//ROUND_ROBIN:transaction将按收到的顺序进行处理
cfg.slave_cfg[0].reordering_algorithm = svt_axi_port_configuration::PRIORITIZED;
先将排序算法设置为PRIORITIZED优先级,在axi_slave_reorder_sequence中设置相应的reordering_priority。方式如下
//get req_resp
p_sequencer.response_request_port.peek(req_resp);
`uvm_info("body", "observed a new transaction at monitor..", UVM_LOW)
...
...
status=req_resp.randomize with {
bresp == svt_axi_slave_transaction::OKAY;
addr_ready_delay==0;
foreach (rresp[index]) {
rresp[index] == svt_axi_slave_transaction::OKAY;
}
foreach(wready_delay[i]) {
wready_delay[i] == 0;
}
if (req_resp.xact_type == svt_axi_slave_transaction::WRITE) {
bvalid_delay == 0;
}
if (req_resp.xact_type == svt_axi_slave_transaction::READ) {
foreach(rvalid_delay[k]) {
req_resp.rvalid_delay[k]== 0;
}
}
};
if(!status)
`uvm_fatal("body","Unable to randomize a response")
if(req_resp.xact_type == svt_axi_slave_transaction::WRITE) begin
///
//assign reordering priority based on txn id
if(req_resp.id == 3) begin
req_resp.reordering_priority = 2;
end
else begin
req_resp.reordering_priority = 1;
end
put_write_transaction_data_to_mem(req_resp);
end
//for read
else begin
//replace number to x
if(req_resp.id==xx) begin
req_resp.reordering_priority = x;
end
else begin
req_resp.reordering_priority = x;
end
get_read_data_from_mem_to_transaction(req_resp);
end
当req_resp的id为3时,reordering_priority为2,否则为1,完成以上设置。将num_outstanding_xact改为8,0~7transaction在第一个transaction完成之前完成排队。
除了3以外,其他的transaction的reordering_priority的值是一致的。如果多个transaction的优先级相同,将按照收到的顺序进行处理。对于写来说,reordering_priority的值指示与write_resp_reordering_depth指示深度内的剩余写transaction相比,给当前transaction发送响应的优先级。对于这个优先级的指定,可以将8个transaction按照自己想要的顺序进行reordering_priority的给值。用case或者多写几个if语句。比如我想resp以以下顺序发回来
7、6、1、5、2、3、4、0
将排序算法设置为RANDOM。
read data
sequence中,当如果req_resp.xact_type不等于WRITE,那么就是READ对应的response data。
if(req_resp.id==6) begin
req_resp.reordering_priority = 2;
end
else begin
req_resp.reordering_priority = 1;
end
具体流程跟上面差不多,就略了。
PRIORITIZED
read_data_interleave_size:指定在与来自不同transaction的读取数据交错之前必须保持在一起的读取数据的节拍数。 当设置为 0 时,不允许交错。 当设置为 1 时,对交错没有限制。
.....未完