type
status
date
slug
summary
tags
category
Property
Nov 30, 2023 02:47 PM
icon
password
属性
属性 1
描述
Origin
URL
SystemVerilog 项目实践之 AHB-SRAMC(1)(AMBA 总线介绍)
- AMBA 总线概述
- AHB(重中之重)
- APB
- 不同 IP 之间的互连
注:AMBA 总线除了 APB 和 AHB 之外,还有 ASB,不过用的少,所以这里不再作为重点!另外,我们 AHB-SRAMC 项目只用到的是 AHB Slave 侧的,所以倒不是说非得把 AHB 搞的很精通才能做这个项目。其实作为 slave 来讲,用到的仅仅是 AHB 协议的简化版本:AHB-Lite。
2.1、系统总线简介
- 系统芯片中各个模块(IP)之间需要有接口来连接
- 总线作为子系统之间共享的通信链路
- 共享的话,每个 slave 都会划分地址空间
- 直连的话(点点通信),不需要划分地址空间,但是成本高且不易扩展
- 优点
- 低成本
- 方便易用(可扩展强)
- 缺点
- 会造成性能瓶颈(涉及命令分配、排队和冲突问题)
2.2、AMBA 2.0
- Advanced Microcontroller Bus Architecture
- 片上总线的标准
- 定义了三种总线
- AHB(Advanced High-performance Bus)
- 实际中用的更多的是变种的:AHB-Lite
- ASB(Advanced System Bus)【了解即可】
- APB(Advanced Peripheral Bus)
- 用在 Slave 中
- AMBA2.0 升级到 AMBA3.0 增加了 AXI 协议,主要应用场景是复杂高速系统。
2.3、AMBA 发展历史
- AMBA 1.0
- ASB 和 APB
- AMBA 2.0
- AHB,ASB 和 APB
- AMBA 3.0
- AMBA Advanced eXtensible Interface(AXI)
- AMBA 4.0
- AXI Coherency Extensions(ACE)【多核一致性】
2.4、一个典型的 AMBA 2.0 系统
注:我们要验证的是 AHB-SRAMC 模块,即要将 AHB 接口的数据转换为 SRAMC 的数据然后写进去,所以学习 AHB 是必须的!
- 处理器和其他主设备 / 从设备都是可以替换的
2.5、AMBA2.0 AHB
- 高速总线(针对 APB)、高性能
- 2 级流水线操作
- 可支持多个总线主设备(数量没有限制)
- 支持 burst 传输(真正 Burst 传输发扬光大的是在 AMBA3.0 的 AXI)
- AMBA 13’00
- 总线带宽:8/16/32/64/128 bits(32 bits 用的最多)
- 上升沿触发操作
注:AHB 相对于 APB 提升的话,主要在于两级流水!
- Q:什么是 Burst 传输?
A:总线的命令无外乎是地址(ADDR)和数据(DATA)。在总线传输的时候,single 时序规定的比较死,需要两拍才能完成地址和时序传输,如下图所示。
通常总线带宽是 32bits,即可以读取 4 个地址的数据。对于传统 single 传输,需要在第一个地址周期发送
ADDR = 0x50
,便可以在第二个数据周期读取地址0x50/0x51/0x52/0x53
组成的 32 位数据。再想读接下来的 4 个地址数据,需要再在第一个地址周期发送ADDR = 0x54
,便可以在第二个数据周期读取地址0x54/0x55/0x56/0x57
组成的 32 位数据。这样读取下来,一共花费了 4 拍。而 Burst 传输要想读取上述 2 个 32 位数据,需要在第一个地址周期发送
ADDR = 0x50
和INC2
(表示需要从 0x50 这个地址连着读 2 个 32 位数据),那么可以在第二个数据周期读取一个 32 位数据,在第三个数据周期再读取一个 32 为数据,一共花费了 3 拍。同理,多读 N 个数据,那就发送地址之外再发送
INCN
即可,一共需要N+1
拍。- Q:2 级流水线操作是什么意思?
A:流水操作直接体现就是在进行地址 1 发送的时候,可以读取地址 0 对应的数据,如下图所示。
2.6、AMBA2.0 APB
- 低速总线、低功耗
- 接口简单
- 在 Bridge 中锁存地址信号和控制信号
- 适用于多种外设(因为外设就是按照人家的规范来做的接口,肯定能挂上去了)
- 上升沿触发
2.7、AHB 组成部分
注:以下组成部门并不是所有 SoC 都需要。
- AHB 主设备(master)
- 发起一次读 / 写操作
- 某一时刻只允许一个主设备使用总线
- CPU、DMA、DSP…
- AHB 从设备(slave)
- 响应一次读 / 写操作
- 通过地址映射来选择使用哪一个从设备
- 外部存储器控制器 EMI、APB bridge
- AHB 仲裁器(arbiter)
- 允许某一个主设备控制总线
- 在 AMBA 协议中没有定义仲裁算法
- master 之间是按照公平轮询的
RR
调度原则,还是按照绝对优先级的SP
调度原则? - 在实际开发中,我们使用
RR
较多
- AHB 译码器(decoder)
- 通过地址译码来决定选择哪一个从设备
2.8、APB 组成部分
- AHB2APB Bridge
- 可以锁存所有的地址、数据和控制(读写控制)信号
- 进行二级译码来产生 APB 从设备选择信号
- APB 总线上的所有其他模块都是 APB 从设备(没有主设备)
2.9、AMBA 协议其他有关问题
- 与工艺无关(协议实现出来的是逻辑,即 RTL 代码)
- 没有定义电气特性(定义的仅仅是逻辑的时序关系,且芯片内部使用,与电压无关)
- 仅在时钟周期级定义时序
- 提供时序(这里指物理实现时序,可不用过多关注)参数依赖于所采用的的工艺和工作频率
- 举例:不是说 APB 只能跑 100M,且协议也没有规定 APB 必须为 100M,需要根据选的工艺和自己要实现的性能要求确定运行的频率。如选 16nm 可以跑到 300M,选 65nm 可以跑到 100M!【总结:跟实际应用有关,与协议规定无关。】
2.10、例:DMA
注:下面的示例代码是伪代码。
SystemVerilog 项目实践之 AHB-SRAMC(2)(AHB 协议基本要点)_ahb 总线 verilog 实现
- 基本 AHB 信号
- AHB 传输
2.1、一个典型的 AMBA 2.0 系统
2.2、AHB 总线互连
AHB 总线从上图可以看到主要有三种类型的信号需要传输:
- HADDR
- 方向为 Master 到 Slave
- HWDATA
- 方向为 Master 到 Slave
- HRDATA
- 方向为 Slave 到 Master
总线上有多个 Master 和 Slave,但是总线每个时刻只能有一个 Master 访问 Slave,因此需要一个 Arbiter 来仲裁地址(HADDR)和写数据(HWDATA)。具体手段,在上图中就是通过 Arbiter 来选择 MUX 的某个输入信号,然后将 MUX 的输出信号送到各个 Slave(共享总线的体现),各个 Slave 分别去译码,译中了之后会进行接收。每个 Slave 地址空间在系统中是唯一的。
各个 Slave 的读数据(HRDATA)信号输入到 MUX 的输入端,然后通过 Decoder 来选择 MUX 的某个输入信号,然后将 MUX 的输出信号送到各个 Matser(共享总线的体现)。这个 Decoder 是 HADDR 过来的,会去做译码,通过译码会知道这个命令是哪个 slave 所接收的,同样道理会去选择哪个 slave 返回的数据,然后返回到 master 中。
2.3、AHB 传输
上图着重介绍了 AHB 传输的流程:首先 Master 发起一个请求给仲裁器(图中未标出),仲裁器会根据各个 Master 的请求把结果发送出来,分别去选择对应 Master 地址 MUX 和数据 MUX 输入。然后送到各个 Slave,Slave 本身会进行译码,决定要不要接收!
允许某个主设备控制总线含义:运行某个命令占用总线。举例来说:Master1 运行读命令访问 Slave2,得到仲裁了,Slave2 返回响应之后,这个命令才算结束。结束之后,Arbiter 才会将总线释放,去仲裁下一轮。对于 Slave 来讲,它会根据地址进行译码!
拉高 HREADY 信号,总线传输完成含义:Slave 完成之后,在返回 Data 的同时会有一个握手 Ready 返回。代表我的这次访问已经 OK 了,告诉 Master 你的这次访问结束了,这样又可以重新申请总线了。
注:这个图面试的时候突击,学习的时候可以先做了解,更重要的还是后面将要介绍的 AHB 时序。另外,AHB 总线目前很成熟都有现成的 IP,通常不会要求面试者去设计,验证也非常成熟,故更多聚焦在 Slave 口的时序上!
2.4、Dummy/Default Master
2.4.1、Dummy Master(用的不多)
- Granted when all masters SPLIT
- Dummy Master 意即 哑巴的 Master,即只有当其他的 Master 没有响应的时候,它才会响应。防止总线挂死设计的一个 Dummy Master。
- Generates IDLE cycles only
- IDLE 是 TRANS 中的一个类型,会有 BUSY/IDLE 这些状态
- Typically Master #0
- 通常会把 Master0 作为 Dummy Master
- Granted when Locked master gets SOLIT response
(后面看到 AHB 时序,再回过头来看这些,因为这里面涉及一些信号,诸如:Locked、IDLE…)
2.5、Default Slave
我们地址空间划分,空间很大,每个 IP 占据了一部分空间后,还有一部分空间是没有 IP 占用的,这部分空间叫默认空间。如果没有默认空间,那么命令过来,没有响应返回(握手机制),整个系统就会挂死。
2.6、AHB 信号
2.7、基本 AHB 信号
- HRESETn
- 低有效
- HADDR[31:0]
- 32 位系统地址总线
- HWDATA[31:0]
- 写数据总线,从主设备写到从设备(M → S)
- HRDATA[31:0]
- 读数据总线,从从设备读到主设备(S → M)
- HTRANS
- 指出当前传输的状态
- NONSEQ(10)、SEQ(11)、IDLE(00)、BUSY(01)
- NONSEQ(10)、SEQ(11)的使用目前在工业界是不做区分的,处理手法都是一样的!
- HSIZE
- 指出当前传输的大小
- HBURST
- 指出传输的 burst 类型
- HRESP
- 从设备发给主设备的总线传输状态
- OKAY、ERROR、RETRY(重传,很少用)、SPLIT(分离,很少用)
- HREADY(返回数据是否有效)
- 高:从设备指出传输结束
- 低电平:从设备需延长传输周期
2.8、基本 AHB 传输
- 两个阶段
- 地址周期,只有一个 cycle(控制信号和地址信号在同一拍)
- 数据周期,由 HREADY 信号决定需要几个 cycle
- 流水线传送
- 先是地址周期,然后是数据周期
2.8.1、一次无需等待状态的简单传输
- 第一条竖黑线处:Master release address and control
- 第二条竖黑线处:Slave sample the address and control
- 第三条竖黑线处:Master sample the data
Q:如果 slave 没有 ready?
- A:
HREADY
在该周期为低!
2.8.2、需要两个等待周期的简单传输
- 经过 3 拍
HREADY
才为高,才能进行数据读取和数据写入操作。
2.8.3、流水线(Pipeline)
- 流水,即地址和数据同时发。
2.8.3、Burst Transfer(基本没用,作为了解即可!)
2.9、传输类型
- HTRANS[1:0]:当前传输的状态
- IDLE、BUSY、NONSEQ、SEQ(后两个合并用,不做区分)
- 00:IDLE(用得少)
- 主设备占用总线,但没进行传输
- 两次 burst 传输中间没有主设备发 IDLE
- 01:BUSY(用得少)
- 主设备占用总线,但是在 burst 传输过程中还没有准备好进行下一次传输
- 依次 burst 传输中间主设备发 BUSY
- 10:NOSEQ【single】
- 表明一次单个数据的传输(single)
- 或者一次 burst 传输的第一个数据
- 地址和控制信号与上一次传输无关
- 11:SEQ【Burst】
- 表明 burst 传输接下来的数据
- 地址和上一次传输的地址是相关的
注:实际使用的时候直接判断 HTRANS 的高位,为 1 表示有效(即 NOSEQ/SEQ 不做区分)。对于 slave 来讲也是不做 SEQ 和 NOSEQ 区分的,因为我们通常会把 ADDR 传过来,不会去关注是 single 还是 burst!
注:这里仅仅作为概念去记忆即可,另外需要知道的一点,只有 Burst 才有 SEQ,Single 的时候只有 NOSEQ!
2.10、传输类型举例
2.11、其他 AHB 控制信号
- HWRITE
- 高电平(1):写
- 低电平(0):读
- HSIZE[2:0]
- 000:8bits 100:128bits
- 001:16bits 101:126bits
- 010:32bits 110:512bits
- 011:64bits 111:1024bits
- 最大值受总线的配置所限制
- 通常使用 32bits(010)
- HPORT[3:0](不怎么用)【了解即可】
- HPORT[0]:OPCODE/DATA(操作数 / 数据)
- HPORT[1]:USER/PRIVILGED(普通用户 / 特权用户)
- HPORT[2]:Bufferable/Non-Bufferable
- HPORT[3]:Cacheable/Non-Cacheable
注:AHB 现在多用于小的 MCU,HPORT 基本不会去用!
2.12、AHB 控制信号小结
2.13、Review
Q:地址译码器的地址从哪里来?
- A:系统地址空间划分设计规定出来的,不同项目空间划分不同!每个 AHB Slave 都有一个 HSEL,HSEL 同时只会有一个有效!
Q:master 一次发 4 个地址,是对应不同的 slave 吗?
- A:4 个地址要对应一个 slave,四个地址通常来讲是连续的。
Q:HSIZE 是说地址还是数据传输位宽?
- A:HSIZE 指的是有效传输数据位宽。数据传输位宽一共是 32 位,通过 HSIZE 可以规定 32 位里面是有效传 8/16 位还是 32 位,没有 24 位。
- 如果有效 8 位,具体 4 个 8 位当中的哪个 8 位,由地址的 [1:0] 决定。如果地址 [1:0]=0,表示数据的[7:0] 有效;如果地址 [1:0]=1,表示数据的[15:8] 有效;如果地址 [1:0]=2,表示数据的[23:16] 有效;如果地址 [1:0]=3,表示数据的[31:24] 有效。
地址总线固定是 32 位(32 系统),那么地址空间相当于 4G。
Q:HBURST 作用?
- A:实际工程中这个信号其实没啥作用。协议中规定了:命令与命令之间访问地址空间连续,就可以第一个命令推算下一个命令地址。
- eg:
BURST 2
;0x000C -> 0x000C 0x000D 0x000E 0x000F ; 0x0010 -> 0x0010 0x0011 0x0012 0x0013;作用:我发了一个命令且地址是 0x000C,并告诉这个命令是 BURST 2,代表我会连续发 2 个 32 位地址空间的访问。由于 AHB 协议中每个命令是把地址带上的, 故做 slave 的时候一般不看 HBURST 信号。
面试常问:画一画 AHB 时序信号?主要信号名字?每个信号作用?
SystemVerilog 项目实践之 AHB-SRAMC(3)(AHB 继续深入)_ahb ic 验证
文章目录
- 1.1、地址计算举例1.2、INCR Burst1.3、WRAP8 Burst1.4、INCR4 Burst1.5、WRAP4 Burst1.6、未定义长度的 Burst 传输1.7、Example LDM AHB Activity1.8、注意1.9、INCR Burst over 1k boundary
- 4.1、AHB 仲裁信号(了解)4.2、仲裁信号解释(了解)4.3、仲裁举例4.4、总线主设备 Grant 信号4.5、几点说明(了解即可)4.6、SPLIT 传输过程4.7、防止 DeadLock(死锁)
一、BURST 传输(了解)
- AHB Burst 操作
- 4 beat(4 * 4Byte = 16Byte)、8 beat、16 beat、单个字节传输、未定义长度的传输
- 支持 incrementing (递增 0 -> 4 -> 8 -> C -> 10 -> 14 -> …)和 wrapping (0 -> 4 -> 8 -> C -> 0 -> 4 -> … 回环传输)两种 burst 传输
- Incrementing burst
- 地址是上一次的传输地址加 1 beat(4 Byte)
- Wrapping burst
- 例:4 beat 的 wrapping burst 字传输(4 byte)
- 0x34 -> 0x38 -> 0x3C -> 0x30(以 0 4 8 C 为边界)
- 应用场景:Cache 填充
1.1、地址计算举例
- 根据 HSIZE 和 HBURST 来计算地址
- 例:起始地址是 0x48,HSIZE=010(32bits)
- Slave 侧一般不会关注是 INCR 还是什么…,因为 master 也会把地址发过来,我们针对每个命令具体操作即可!
- 如果是 INCR,会根据 HSZIE 决定递增多少!
- 在 BURST 里面,第一个传输类型是 NOSEQ,剩余的都是 SEQ
1.2、INCR Burst
1.3、WRAP8 Burst
- 与 INCR8 唯一区别是在边界需要 WRAP 回来!
- WRAP4:
0 -> 4 -> 8 -> C
回环 - WRAP8:
0 -> 4 -> 8 -> C -> 10 -> 14 -> 18 -> 1C
回环
1.4、INCR4 Burst
1.5、WRAP4 Burst
1.6、未定义长度的 Burst 传输
- 注意 HSIZE 为 Halfword,即 2Byte 那么 HADDR 加的就是 2;如果 HSIZE 为 Word,即 4Byte,baneHADDR 加的就是 4.
1.7、Example LDM AHB Activity
- 功能:把首地址 0x34 的数据 load 到 r5-r10 这 6 个寄存器中
- 因为没有 INCR6,所以先 INCR4,再两次 SINGLE
- 当然除了上面的方式,还可以 6 次 SINGLE;还可以先 2 次 SINGLE,在 INCR4…
1.8、注意
- Burst 传输不能穿越 1K 边界(可以防止占用总线过长,导致其他组件挂死)
- 一个从设备最小的地址间隙是 1KB
- NONSEQ -> SEQ -> 1KB Boundary -> NONSEQ -> SEQ
- 主设备不能视图开始一个可能穿越 1K 边界的固定长度的 incrementing burst 传输
1.9、INCR Burst over 1k boundary
注:跨 1K 边界跟操作系统的 page 大小有关系!
Q:0x3FC 到 0x400 为什么是 1K 边界?
- A:首先明确如何判断 1K 边界,如果
地址 / 1k
结果为整数,那么就是 1K 整数倍。addr[31:0] / 2^10
相当于 addr[31:0] 右移 10bit,s 商为addr[31:10]
,小数部分为add[9:0]
,即 addr[9:0] = 10’h000,那么就是 1K 对齐!
- 0x400 对应二进制为
10'b00_0000_0000
,也就是说它是 1K 边界!
- 0x000-0x3FF 为 1K 空间;0x400-0x7FF 为 1K 空间;
二、地址译码
- HSELx:选择从设备(选中谁对应的 HSEL = 1)
- 指出由主设备所选择的从设备
- 由地址译码器来提供选择信号
- 一个从设备应该至少占用 1KB 的存储空间
- 需要一个额外的缺省从设备来映射其他的存储地址
- Decoder 译码器的实现对应到 RTL 代码
if..else
语句
2.1、从设备响应
- 所访问的从设备必须响应这次传输
- AHB 是个握手的传输机制,如果从设备不返回 hready 的话,master 会一直等,下一次命令就无法传输
- 从设备可能返回的响应:
- 完成这次传输(OKAY)
- 插入等待状态(HREADY 信号)(IDLE)
- 发出错误信号表示这次传输失败(RETRY)
- 延迟传输,使得总线可用于其他传输(SPLIT)
- HREADY:transfer done
- HRESP[1:0]:transfer response
- 00:OKAY
- 成功
- 01:ERROR
- 失败
- 10:RETRY
- 传输未完成
- 请求主设备重新开始一个传输
- 11:SPLIT
- 传输未完成
- 请求主设备分离一次传输(让出总线仲裁权,让其他 master 使用!)
2.2、两周期的响应
- HRESP[1:0]
- OKAY:单周期响应
- ERROR:两周期响应
- RETRY:两周期响应
- SPLIT:两周期响应
- 总线的流水特性需要从设备两个周期的响应(工程上有点不太实用)。可以使得主设备有足够的时间处理下一次传输
2.3、Slave Response
- 假如有 error 了,就可以通过 HRESP 来返回。但实际上,假如有 ERROR 了是通过内部寄存器上报的,不会通过总线上报!
- 这个实际中也没怎么用,ready 握手机制就已经够用了,ready 一直未低,master 就会去等。设计协议的时候,为了兼容性强,设计了可以立即返回 BUSY 的这种功能,这样 master 就不用等了,可以处理其他命令了!但是实际中等待时间也不长,故用 ready 还是比较多的!
2.4、Retry 响应
- Retry 需要两个时钟周期
2.5、Rerty 和 SPLIT 的不同
- 主要区别在于仲裁的方式
- RETRY :arbiter 会继续使用通常的优先级
- SPLIT:arbiter 会调整优先级方案以便其他请求总线的主设备可以访问总线(释放总线让其他 master 得以访问)
- 总线主设备应该用同样的方式处理 RETRY 响应和 SPLIT 响应。
三、数据总线
- 不是三态总线,读总写和写总线是分开的
- Endian(大小端)
- 在 AMBA 协议没有定义,由 Master 定义
- 主设备和从设备应该采用同样的大小端
- 不支持动态大小端
- 对于 IP 设计,只有应用面比较广泛的应用程序才支持两种 Endian
小端:A3-[bit31-bit24];A2-[bit23-bit16];A1-[bit15-bit8];A0-[bit7-bit0]
大端:A0-[bit31-bit24];A1-[bit23-bit16];A2-[bit15-bit8];A3-[bit7-bit0]
3.1、32 bit 小端数据总线的有效字节
3.2、32 bit 大端数据总线的有效字节
作为 AHB 来讲,作为通道是看不到大小端的!
四、主设备
4.1、AHB 仲裁信号(了解)
注:总线本身没有规定仲裁算法,常用的仲裁算法有:RR(公平轮询)/SP(绝对优先级)/WRR(带权重 RR)
- 信号中的
x
代表不同的 master,2 个 master,x 就是 0-1
- HBUSREQx:Master 发起总线申请
- HLOCKx:Master 锁定总线传输
- HGRANTx:Aribiter 回复给 Master 的请求结果
- HMASTER[3:0],上述最大值为 16,但是并不是说 AHB 只能有 16 个 master,可以通过修改位宽来增加 master!
- HMASTLOCK:Master 申请 Lock 之后,Arbiter 的反馈
- HSPLITx[15:0]:Slave 发了 Split 之后,根据 Split 去调整 Master 之间的优先级,跟调度算法有关
4.2、仲裁信号解释(了解)
- HBUSERQ(相比较用的多)
- 总线请求
- HLOCKx
- 高电平:主设备请求锁定总线
- HGRANTx(相比较用的多)
- 指出主设备 x 可访问总线
- 主设备 x 控制总线:HGRANTx = 1 且 HREADY = 1
- master1 可访问返回 001;master2 可访问返回 010…(注意 one-hot 编码方式)
- HMASTER[3:0]
- 指出哪个主设备正在进行传输
- master3 选中返回 3,master5 选中返回 5…(二进制编码)
- HMASTLOCK
- 指出主设备正在进行一次锁定传输
- HSPLITx[15:0]
- 从设备用这个信号告诉仲裁器哪个主设备允许重新尝试一次 split 传输
- 每一位对应一个主设备
注:仲裁面试的概率比 BURST 还要低。
现在用 AHB 做系统大总线设计的越来越少,做仲裁也是一般买 IP 来做。
4.3、仲裁举例
- 没有等待状态的 grant
- 有等待状态的 grant
- Burst 传输之后移交总线
4.4、总线主设备 Grant 信号
4.5、几点说明(了解即可)
- 对于固定长度的 burst 传输,不必持续请求总线
- 对于未定义长度的 burst 传输,主设备应该持续送出 HBUSREQ 信号,指导开始最后一次传输
- 如果没有主设备请求总线,则给缺省主设备(dummy master)grant 信号,且 HTRANS=IDLE
- 建议主设备在锁定总线传输结束之后插入 IDLE 传输,以重新仲裁优先级
4.6、SPLIT 传输过程
- 1、由主设备开始传输(M -> S)
- 2、如果从设备需要多个周期才能获取数据,则从设备给出一个 SPLIT 传输响应,从设备记录主设备号:HMASTER。接着仲裁器改变主设备的优先级
- 3、仲裁器 grant 其他的主设备,总线主设备移交
- 4、当从设备准备结束本次传输,将设置给仲裁器的 HSPLITx 信号的相应位
- 5、仲裁器恢复优先级
- 7、仲裁器 grant 主设备,这样主设备可以重新开始传输
- 8、结束
4.7、防止 DeadLock(死锁)
- 当多个不同的主设备试图访问同一个从设备,这个从设备发出了 SPLIT 和 RETRY 信号,这时很可能发生 deadlock
- 从设备最多可以接收系统中 16 个主设备的请求,只需要记录主设备好(忽略地址和控制信号)
- 实际可以自己做扩展
- 给出 RETRY 响应的从设备在某一时刻只能由一个主设备访问。
- 可以使用一些硬件保护机制,比如 ERROR
注:SPLIT 基本很少用!
五、AHB 设备接口
- AHB Master
- AHB Slave
- AHB Aribiter
- AHB Decoder
5.1、AHB 主设备接口(要会画)
输入
- 来自 Arbiter grant 信号
HGRANTx
,表示获得总线使用权。Master 有多个,M0 那么 HGRANTx 为 0;M1 那么 HGRANTx 为 1。
- Slave 返回的 HREADY,不管读或者写,为高表示当前命令处理完了,可以发送下一个命令了。同时还会伴随一个 HRESP 回来,如果是 00 表示 OK,01 表示 ERROR,10 表示 RETRY,11 表示 SPLIT(给仲裁器用的,master 本身不会关注)
- 接着是时钟信号和复位信号,复位信号中的 n 表示 negative,表示低电平有效!
- 如果是读命令的话,Slave 会从 HRDATA 返回读数据
- Master 会返回 HBUSREQx 和 HLOCKx 两个信号给 Arbiter
- 对于 Slave 主要会发送一个地址 HADDR,地址会伴随着其他的控制信号。比较重要的控制信号就是 HTRANS,00 表示 IDLE,01 表示 BUSY,10 表示 NOSEQ,11 表示 SEQ。SEQ 和 NOSEQ 对于 Slave 来讲,在实际使用没太大区别。只是协议上规定了如果发的是一个 BURST 操作,那么第一个命令需要用 NOSEQ 来表示,其余命令用 SEQ 来表示;如果发的是 SEQ,每个命令跟命令之间的地址没什么关系,那你就都是 NOSEQ 表示!
- HWRITE 信号表示读还是写
- HSIZE 信号指总线 32 位中,多少是有效的。000 8bits;001 16bits;010 32bits
- HBURST 信号指发的命令前后地址之间有没有关系,000 single:前后地址之间没有关系; 001 INCR:前后地址根据 HSIZE 递增(1/2/4 byte,没有 3 byte)。在 AHB 上用的不多,但是在 AXI 上用多,因为 AXI 上引入了一种叫
outstanding
的机制。AHB 只是两级流水,HBURST 没起到多大作用。对于 Slave 来讲不关注 HBURST 信号,一样能根据地址(不管前后地址有无关联)一个个处理命令。
- HPORT 信号是做一个保护,data 来自什么地方。没啥用不用关注,重点关注:
HWRITE、HSIZE、HTRANS
这三个信号!
5.2、AHB 从设备接口(要会画)
- HSEL 是从译码器 Decoder 来的,因为我们的总线是共享的,所以数据肯定会到每一个 Slave,但是每一次只是访问其中一个 Slave。因此会通过 HADDR 做一次译码,根据 AHB Slave 的地址范围,译码到你的话,会把对应的 HSELx 拉高。HSELx 为高,命令才是访问到我的,同时看看 HTRANS 是不是有效(NOSEQ 或 SEQ)代表命令是有效的。
- 下面 Split-capable 是为了实现 SPLIT,一般来讲 SPLIT 容易出现 DeadLock,所以一般不去实现,这里仅作为了解即可!而且现在 SPLIT 的处理也不会等太长时间。
5.3、AHB Arbiter(要会画)
- 上图仅仅以三个 Master 来示意 AHB Aribiter,并不是说只能有 3 个 Master。AHB 总线默认可以挂载 16 个 Master,当然我们也可以通过修改位宽达到挂载更多 Master 的目的!
- AHB 的 HADDR 感觉没啥用,它更多的还是关注 HUBUSREQ 是哪个 Master 过来的,然后对应给仲裁输出 HGRANT。相当于 HBUSREQ 和 HGRANT 相互之间进行握手,完成仲裁的控制。
- HSPLIT 信号会让 Abriter 进行优先级调整
5.4、AHB Decoder(要会画)
- Decoder 的作用就是输入 HADDR,然后根据 Slave 的空间划分,进行第一级译码操作。HSELx 分别对应一个 Slave。
- RTL 实现就是
if...else
或者case
六、Typical Multi-layer example(了解)
- 在一个系统中 Master 和 Slave 还可能是多级的
- Slave Mux 是将第二级 Slave 的地址范围译出来,方面后面选择!
- 并行访问带宽会大些
七、AHB-Lite(业界目前用的比较多的)
AHB 通过前面的学习,我们知道它是一个多 Master 多 Slave 的协议,但是在实际项目中我们用的更多的是 AHB-Lite。它是一款简化的 AHB 协议只有一个 Master,所以与 AHB 相比少了仲裁的机制。也正因为这个原因,少了许多繁杂的信号,可以帮助我们更好的理解和上手 AHB 协议。本次的 AHB-SRAMC 项目也是基于 AHB-Lite 协议的!
- AHB 的 Lite 体现在没有 Aribiter,就是 1 个 Master 多个 Slave
- Master 的信号中:没有 HBUSREQ 和 HGRANT
- Slave 的信号中:没有 RETRY 和 SPLIT
- AHB Lite 化繁为简,所以更实用。
- 后面的 AHB SRMAC 用的也是 AHB-Lite
八、AHB 总结
- 主要组成部分
- Master、Slave、Aribiter、Decoder(多 Slave 选择)
- 传输的过程
- 流水线机制
- Address Phase 和 Data Phase
- 如何提高性能
- 流水线
- 注意:Burst Read/Write 并不能提升性能,因为数据该多少拍还是多少拍,并没减少!
- 仲裁机制
- 总线控制权的移交(调度)
- Slave 短时间内无法响应
- HREADY 信号拉低
- Slave 长时间内无法响应(长时间?短时间?怎么界定?功能鸡肋!)
- 插入 SPLIT/RETRY(到了 AHB-Lite 这个被去掉了)
- Master 不能进行传输
- 插入 BUSY(不实用)
- 直接 HTRANS 最高位置位 0,无效之后 Slave 就不进行接收了!
九、AHB 的应用建议
- Arbiter 的优先级可以配置
- Slave 长时间不能响应的话,一般不支持 SPLIT 响应(它会 DeadLock),使用 RETRY 响应
- 总线上如果只有一个 Master 的话,可以使用 AHB-Lite 协议,不用 Aribiter
- 设计一个新的 IP 时,要仔细核对 AMBA 的 Feature 和 IP 所支持的 Feature 是否匹配
十、实现
- 如果设计中既有主设备端口又有从设备端口(eg:DMA、SD-HOST)
- 通过主设备(Master)端口读 / 写数据
- 通过从设备(Slave)端口配置寄存器等
- 如处理器(CPU)设置的一些参数(配置寄存器)
SystemVerilog 项目实践之 AHB-SRAMC(4)(AHB 重点回顾,要点提炼)
1.1、AMBA 发展史
- AMBA1.0: ASB 协议和 APB 协议;
- AMBA2.0: AHB 协议、ASB 协议和 APB 协议;
- AMBA3.0: 增加了 AXI 协议(了解);
- AMBA4.0: ACE 协议(了解)
本文主要介绍 AMBA2.0 (Advanced Microcontroller Bus Architecture,先进微控制总线结构),主要定义了三种总线:
- AHB:Advanced High-performance Bus(先进高性能总线) 高速高性能总线;支持 2 级流水操作(优势)
- APB:Advanced Peripheral Bus(先进外围总线) 低速总线、低功耗;接口简单
- ASB:Advanced System Bus(先进系统总线)
1.2、典型的 AMBA 系统
AHB 总线的强大之处在于它可以将微控制器(CPU)、高带宽的片上 RAM、高带宽的外部存储器接口、DMA 总线 master、各种拥有 AHB 接口的控制器等等,连接起来构成一个独立的完整的 SOC 系统。不仅如此,还可以通过 AHB-APB 桥来连接 APB 总线系统。
AHB 可以称为一个完整独立的 SOC 芯片的骨架。
2.1、AHB 总线组成
完整的 AHB 总线由四个部分组成:
- ① AHB 主设备 Master; 发起一次读 / 写操作; 某一时刻只允许一个主设备使用总线
- ② AHB 从设备 Slave; 响应一次读 / 写操作; 通过地址映射来选择使用哪一个从设备;
- ③ AHB 仲裁器 Arbiter; 允许某一个主设备控制总线;
- ④ AHB 译码器 Decoder; 通过地址译码来决定选择哪一个从设备;
2.2、AHB 总线互连示意图
2.3、AHB 操作概述
- 1、有需要占用总线的 Master 向 arbiter 发出请求,arbiter 授权给指定的 master。任一时间周期只有一个 master 可以接入总线,对其指定的 slave 进行读写操作。
- 2、获得总线授权的 master 开始 AHB 传输,首先发出地址和控制信号,提供地址信息、传输方向、带宽和 burst 类型。
- 总线统一规划 slave 的地址,译码器根据地址和控制信号确定哪个 slave 与 master 进行数据通信。数据传输通过数据总线完成。为避免出现三态总线,AHB 将读写总线分开,写数据总线用于从 master 到 slave 的数据传输,读数据总线用于从 slave 到 master 的数据传输。每笔传输包括一个地址周期(控制信号和地址信号在同一拍),一个或多个数据周期。地址周期不能被扩展,因此 slave 必须在一个周期内采样地址信号。数据周期可以通过 HREADY 信号扩展,但 HREADY 为低时给传输加入一个等待状态以使 slave 获得额外的时间来提供或采样数据,另外 slave 通过响应信号 HRESP 反映传输状态。
- 3、AHB 支持 Burst 数据传送(用的少),可以自动递增地址。递增地址方式分为:(Incrementing Burst )持续递增(INCR 或者 INCRx)与(Wrapping Burst)回环传送。
- 4、一般情况下 master 完成完整的 burst 传输,arbiter 才会授权给其他的 master 接入总线,然而为避免过大的判决延迟,arbiter 也可能打断 burst 传输。在这种情况下 master 必须再次接入总线以进行中断的 burst 剩余部分的传输。
2.4、AHB 基本传输阶段
AHB 的传送模式包含二个阶段。第一阶段为地址的传递,另一阶段为数据的传递。
- 地址传输阶段; (address phase): 一个时钟周期(控制信号同地址信号在同一个周期)
- 数据传输阶段;(data phase): 一个或多个时钟周期 (以 HREADY 信号控制周期数目).
3.1、AHB 信号描述(重要)
信号名 | 含义 | 源 | IO | 描述 |
HCLK | 总线时钟 | clock source | 各 module 输入 | 总线时钟,上升沿采样 |
HRESETn | 复位 | reset controller | 各 module 输入 | 总线复位,低电平有效 |
HADDR[31:0] | 地址总线 | Master | Decoder;Mux to Slave; Arbiter | 32 位系统地址总线 |
HTRANS[1:0] | 传送类型 | Master | mux to slave | 当前传输类型 00-IDLE, 01BUSY, 10-NONSEQ, 11-SEQ |
HWRITE | 传送方向 | Master | mux to slave | 1 为写,0 为读 |
HSIZE[2:0] | 传送带宽 | Master | mux to slave | 每一个 transfer 传输的数据大小,以字节为单位,最高支持 1024 位 |
HBURST[2:0] | 批量传送 | Master | mux to slave | burst 类型,支持 4、8、16 burst,incrementing/wrapping |
HPROT[3:0] | 保护控制 | Master | mux to slave | 保护控制信号,需要 slave 带保护功能,一般不用 |
HWDATA[31:0] | 写数据总线 | Master | mux to slave | 写数据总线,Master 到 Slave |
HRDATA[31:0] | 读数据总线 | Slave | mux to master | 读数据总线,Slave 到 Master |
HREADY | 传送完成 | Slave | mux to master;arbiter | 控制 HRDATA 的读出数据周期;高:Slave 输出传输结束;低:Slave 需延长传输周期 |
HRESP[1:0] | 传送响应 | Slave | mux to master;arbiter | Slave 发给 Master 的总线传输状态 OKAY, ERROR, RETRY, SPLIT |
HSELx | 从选择 | Decoder | slave | slave 选择信号 |
说明:在实际的传输过程中,一般作为 AHB 总线的 Slave 设备都有 2 根 hready 信号,一个为 input 类型(hready_in),另一个为 output 类型(hready_out)。在 AHB 总线协议中,如果 Master 设备发起读写操作的时候,Slave 设备不能及时响应的话,由 Slave 设备把 hready_out 信号拉低来拖延 Data Phaze 周期。
但是在 Pipeline 操作的时候,本次操作 Data phaze 是下一次操作的 Address phaze,所以作为 Slave 设备在响应 Master 设备的时候,必须先判断一下 Master 设备对上一次其它 Slave 设备的操作是否已经完成。如果完成,则响应主设备的操作;如果没有完成,则等待完成,然后才响应操作。 hready_in 就是 Slave 设备用来判断 Master 设备是否对其它 Slave 设备的操作已经完成的信号。
AHB 仲裁信号(了解,有印象即可)
信号名 | 含义 | 源 | IO | 描述 |
HBUSREQx | Bus 请求 | Master | Master to Aribiter | Master 向 Aribiter 发出的总线使用请求信号 |
HLOCKx | 锁定传送 | Master | Master to Aribiter | 如果一个 master 希望自己在传输期间不希望丢掉总线,则需要向仲裁器发送这个锁定信号 |
HGRANTx | Bus 同意 | arbiter | Aribiter to Master | master 授权信号,当前 bus master x 的优先级最高。当 HREADY 和 HGRANTx 同时为高时,master 获取系统总线的权利。如:同意 master1 可访问返回 001;同意 master2 可访问返回 010…(注意 one-hot 编码方式) |
HMASTER [3:0] | 主设备号 | arbiter | Aribiter to Master | 仲裁器为每一个 master 分配的 ID,指出哪个主设备正在进行传输。如:master3 选中返回 3,master5 选中返回 5…(二进制编码) |
HMASTLOCK | 锁定传输 | arbiter | 具有 split 功能的 slave | 表示当前的 master 正在执行 Locked 操作。这个信号和 HMASTER 有相同的时序 |
HSPLITx[15:0] | 分段请求 | slave | Slave to Aribiter | 从设备用这个信号告诉仲裁器哪个主设备运行重新尝试一次 split 传输,每一位对应一个主设备 |
3.2、基本 AHB 传输(重要)
3.2.1、零等待传输 (no wait state transfer)
- 第一个周期的上升沿(Cycle 1)
- master 驱动地址和控制信号;
- 第二个周期的上升沿(Cycle 2)
- slave 采样地址和控制信号,并将 HREADY 拉高;
- 如果是写操作,master 会在第二个周期的上升沿传输要写入的数据;
- 如果是读操作,slave 会在 HREADY 信号拉高后将读取的数据写入总线;
- 第三个周期的上升沿(Cycle 3)
- 如果是写操作,master 获取 HREADY 高信号,表明 slave 已成功接收数据,操作成功;
- 如果是读操作,master 获取 HREADY 高信号,表明此时的读数据有效并且接收下来,操作成功。需要注意,HREADY 信号在数据有效期间必须为高,确保 master 的正确采样。
3.2.2、等待传输 (transfers with wait states)
传送完成时间因等待而延迟,这是由于寻址到较慢的 Slave 单元所造成。当 HREADY 被 Slave 拉低时,会发生等待状态。需要延迟传送的周期时,就会在数据期间将 HREADY 拉低,此时地址与数据都必须延伸。有等待状态的 AHB 传递,下图中可看到在数据模式时,时序必须多花二个周期的延迟等待时间 (HREADY 为 0),Slave 才能正常的接收到 Master 写的数据或准备好 Master 欲读取的数据。
slave 可以及时处理 master 请求,但也可能存在 slave 太慢不能立即处理的情况。这时需要让 master 稍微等一等,需要 slave 插入一些等待的状态。如上图所示,HREADY 信号在第二和第三周期拉低,意在告诉 master,slave 不能立即处理,需要 master 等待 2 个周期。在这里需要注意两点:
- 1、如果是写操作,master 需要在等待期间保持写数据不变,直到本次传输完成。
- 2、如果是读操作,slave 不需要一开始就给出数据,仅当 HREADY 拉高后才给出有效数据。
3.2.3、多重传送 (multiple transfer) - 流水操作 Pipeline
一次完整的数据传送会有多个传送周期,如下图下一笔地址可与上一笔数据同时在总线上,时序图的说明如下:
扩展数据周期的一个负效应是必须延长相应的下一笔传输的地址周期。A0 和 A2 为零等待传输,A1 加入了一个等待周期,因此相应的 A2 地址周期要进行扩展。
- 第一个周期,master 发起一个操作 A0,并驱动地址和控制信号;
- 第二个周期,slave 收到了来自总线的请求,将 HREADY 信号拉高;
- 第二个周期上升沿后,master 发现有操作 A1 需要执行,并且检查到上一周期的 HREADY 为高,则发起第二个操作 A1;
- 第三个周期,master 获取 HREADY 信号为高,表示操作 A0 已经完成;
- 第三个周期上升沿后,master 发现有操作 A2 需要执行,并且检查到上一周期的 HREADY 为高,则发起第三个操作 A2;
- 第三个周期上升沿后,slave 由于繁忙插入了一个等待状态,将 HREADY 拉低;
- 第四个周期,master 获取 HREADY 信号为低,知道 slave 希望等待,于是 master 保持和上一拍一样的信号;
- 第四个周期,slave 处理完了事务,将 HREADY 信号拉高,表示可以继续处理;
- 第五个周期,master 获取 HREADY 信号为高,知道 slave 已经可以处理 A1 操作;
- 第五个周期上升沿后,A1 操作完成;
- 第六个周期上升沿后,A2 操作完成。
需要注意几点:
- HREADY 在一定程度上表示了 slave 的 pipeline 能力,在 AHB 中是 2 个 pipe,也就是总线上最多存在 2 个未处理完的 transfer。
- 故,只有当总线上未完成的 transfer 少于 2 个时,master 才能发起操作。
3.3、AHB 控制信号
3.3.1、传送状态 HTRANS[1:0]
在 AHB 总线上,Master 的传送状态可由 HTRANS[1:0] 来表示,这两位所代表的意义如下:
- 00:IDLE
- 01:BUSY
- 10:NOSEQ
- 11:SEQ
注:在实际使用中我们将 NOSEQ 和 SEQ 不作区分,都称为有效传输状态。更多介绍可参考前面的博客。
3.3.2、批量传送 HBURST[2:0]
实际工程中这个信号其实没啥作用。只是协议中规定了这个信号:命令与命令之间访问地址空间连续,就可以第一个命令推算下一个命令地址。
- eg:
BURST 2
;0x000C -> 0x000C 0x000D 0x000E 0x000F ; 0x0010 -> 0x0010 0x0011 0x0012 0x0013;作用:我发了一个命令且地址是 0x000C,并告诉这个命令是 BURST 2,代表我会连续发 2 个 32 位地址空间的访问。由于 AHB 协议中每个命令是把地址带上的, 故做 slave 的时候一般不看 HBURST 信号。
3.3.3、传送方向 HWRITE
HWRITE:表示传送方向(依读或写的动作来决定传送信号的方向)
- HWRITE 拉高时(写),M 必须对写入动作初始化,数据会由 M 放到 HWDATA[31:0] 总线上。
- HWRITE 拉低时(读),M 会对读取动作初始化,被寻址到的 S 会将数据放到 HRDATA[31:0] 总线上。
3.3.4、传送大小 HSIZE[2:0]
传送数据大小由 HSIZE[2:0] 信号控制,表示每次传送的字节数目。
- 000:8bits 100:128bits
- 001:16bits 101:256bits
- 010:32bits 110:512bits
- 011:64bits 111:1024bits
3.3.5、保护控制 HPROT[3:0]
HPROT[3:0] 为总线协议保护信号,用来定义存取的型态与特性,并非所有的 Master 都会传送出 HPROT[3:0],所以除非 Slave 有需要否则不会使用到 HPROT[3:0] 信号。一般来讲该信号很少用到。
3.4、AHB 响应信号
master 发起一笔传输后,slave 可以决定这笔传输的进程,而 master 不能取消已经发出的传输。slave 通过 HREADY 信号反映传输是否完成,通过 HRESP[1:0] 反映传输的状态。
3.4.1、slave 可以如下方式完成一笔传输
- 立即完成一笔传输;
- 延迟一个或几个周期完成传输;
- 传输失败返回 error;
- 延迟传输,释放总线。
3.4.2、传输完成标志 HREADY
- HREADY 为高时传输完成,
- HREADY 为低时传输需要延迟
3.4.3、传输响应标志 HRESP[1:0]
- 00: OKAY—传输完成
- 01: ERROR—传输错误
- 10: RETRY—传输未完成,请求主设备重新开始一个传输,arbiter 会继续使用通常的优先级
- 11: SPLIT—传输未完成,请求主设备分离一次传输,arbiter 会调整优先级方案以便其他请求总线的主设备可以访问总线
3.4.4、地址译码
地址译码器用于为总线上每个 slave 提供选择信号 HSELx,选择信号是通过组合逻辑对地址码译码产生的。只有当前的数据传输完成后(HREADY 为高),slave 才会采样地址和控制信号以及 HSELx。
在一定条件下可能会出现这样的情况:产生 HSELx 信号而 HREADY 为低,在当前传输后 slave 会改变。
每个 slave 最小的地址空间为 1KB,所有的 master 的 burst 传输上限也是 1KB,如此设计保证了不会出现地址越界问题。当一个设计不会用到所有的地址空间时,可能出现访问到一个不存在的地址的情况,这就需要增加一个附加的默认 slave(default slave)来为上面的情况提供一个响应。当 SEQ 或 NONSEQ 传输访问到一个不存在的地址,默认 slave 应该提供 ERROR 响应;当 IDLE 或 BUSY 传输访问到一个不存在的地址,默认 slave 会响应 OKAY。地址译码器会带有实现默认 slave 的功能。
3.4.5、仲裁
仲裁机制保证了任意时刻只有一个 master 可以接入总线。arbiter 决定哪个发出接入请求的 master 可以接入总线,这通过优先级算法实现。AHB 规范并没有给出优先级算法,设计者需要根据具体的系统要求定义。一般情况下 arbiter 不会中断一个 burst 传输,将总线接入权让给其他 master。当然未定义长度的 burst 传输是可以打断的,这要看优先级算法是如何规定的。如果一笔 burst 被打断,master 再度获得接入权限时,会传递剩余的部分。如一笔长度为 INCR8 的传输在传递 3beat 后被打断,master 再次获得接入授权后,会继续传输剩余的 5 beat,剩余部分可以由一个 SINGLE 和一个 INCR4 组成,或者一个 INCR。
- HBUSREQx:master 向 arbiter 发出接入请求的信号。
- HLOCKx:指示是否要进行不可中断的传输,这一信号与 HBUSREQx 同时由 master 向 arbiter 发出。
- HGRANTx:arbiter 产生指示 master 获得授权,当 HGRANTx 信号为高同时 HREADY 为高时,master 可以向总线传输地址信号。
- HMASTER[3:0]:arbiter 产生指示哪个 master 获得授权,这一信号用于地址控制多路来选择哪个 master 接入总线。
- HMASTERLOCK:arbiter 产生指示当前传输是否为锁定序列传输。
- HSPLIT:供支持 SPLIT 传输使用。
- AHB Master
- AHB Slave
- AHB Aribiter
- AHB Decoder
4.1、AHB 主设备接口(要会画)
部分信号释义:
- 来自 Arbiter grant 信号
HGRANTx
,表示获得总线使用权。Master 有多个,M0 那么 HGRANTx 为 0;M1 那么 HGRANTx 为 1。
- Slave 返回的 HREADY,不管读或者写,为高表示当前命令处理完了,可以发送下一个命令了。同时还会伴随一个 HRESP 回来,如果是 00 表示 OK,01 表示 ERROR,10 表示 RETRY,11 表示 SPLIT(给仲裁器用的,master 本身不会关注)
- 接着是时钟信号和复位信号,复位信号中的 n 表示 negative,表示低电平有效!
- 如果是读命令的话,Slave 会从 HRDATA 返回读数据
- Master 会返回 HBUSREQx 和 HLOCKx 两个信号给 Arbiter
- 对于 Slave 主要会发送一个地址 HADDR,地址会伴随着其他的控制信号。比较重要的控制信号就是 HTRANS,00 表示 IDLE,01 表示 BUSY,10 表示 NOSEQ,11 表示 SEQ。SEQ 和 NOSEQ 对于 Slave 来讲,在实际使用没太大区别。只是协议上规定了如果发的是一个 BURST 操作,那么第一个命令需要用 NOSEQ 来表示,其余命令用 SEQ 来表示;如果发的是 SEQ,每个命令跟命令之间的地址没什么关系,那你就都是 NOSEQ 表示!
- HWRITE 信号表示读还是写
- HSIZE 信号指总线 32 位中,多少是有效的。000 8bits;001 16bits;010 32bits
- HBURST 信号指发的命令前后地址之间有没有关系,000 single:前后地址之间没有关系; 001 INCR:前后地址根据 HSIZE 递增(1/2/4 byte,没有 3 byte)。在 AHB 上用的不多,但是在 AXI 上用多,因为 AXI 上引入了一种叫
outstanding
的机制。AHB 只是两级流水,HBURST 没起到多大作用。对于 Slave 来讲不关注 HBURST 信号,一样能根据地址(不管前后地址有无关联)一个个处理命令。
- HPORT 信号是做一个保护,data 来自什么地方。没啥用,不用关注,重点关注:
HWRITE、HSIZE、HTRANS
这三个信号!
每一次的数据传送可分成四种型态,M 用 HTRANS[1:0] 信号来决定此次传送数据的型态,这四种传送型态分别是 IDLE、BUSY、NONSEQ 和 SEQ。
- 第一种数据传送型态为 IDLE 时,表示 M 这时候想要拥有总线的使用权,但并不需要作数据的传送,此时的 S 必须立即作出 OKAY 的响应;
- 第二种数据传送型态为 BUSY,当 M 进行一连续笔数据传递期间,若有些数据无法实时在下一个周期作传送,此时 M 会发出 BUSY 信号来延迟此笔数据的传送,S 这时候也会响应一个和 IDLE 传送型态一样的 OKAY 信号,同时忽略这笔数据的传递;
- 第三种数据传送型态为 NONSEQ,NONSEQ 的传送型态表示此次的传送为单笔数据传送或一连续笔数据传送中的第一笔,因此这种的传送型态,数据的地址和控制信号跟前一笔数据不具有关联性;
- 第四种种数据传送型态为 SEQ,在一连续笔数据的传递中,除了第一笔数据之外,其它的数据传递型态为 SEQ (第一笔为 NONSEQ),这种数据传递的控制信号和前一笔相同,而数据的地址则为前一笔数据地址加上由 HBURST[2:0] 和 HSIZE[2:0] 信号所决定出的地址累加值。
4.2、AHB 从设备接口(要会画)
部分信号释义:
- HSEL 是从译码器 Decoder 来的,因为我们的总线是共享的,所以数据肯定会到每一个 Slave,但是每一次只是访问其中一个 Slave。因此会通过 HADDR 做一次译码,根据 AHB Slave 的地址范围,译码到你的话,会把对应的 HSELx 拉高。HSELx 为高,命令才是访问到我的,同时看看 HTRANS 是不是有效(NOSEQ 或 SEQ,代表命令是有效的)。
仲裁器在决定出哪一个 M 拥有总线使用权之后,会将这个 M 数据地址、控制信号及欲写入 S 的数据选出,并且送至每一个 S,而所选出的数据地址会再经由 AHB 译码器产生唯一的 HSELx 使能信号来启动一 S 的数据传送。M 启动一个数据传送之后,被使能的 S(即 HSELx 为 1 的 S) 会发出 HREADY 信号来决定是否要延长当前数据的传送,若 S 响应 HREADY 为 0,表示此笔数据的传递必须被延迟,若 S 送出的 HREADY 为 1,则表示 S 能够完成此笔数据的传递。
由图中可发现,S 除了用 HREADY 信号来告知此笔数据是否需要额外的延迟时间之外,还会透过 HRESP[1:0] 信号响应当前数据传送的情形,以下将说明四种 S 的响应型态:
- (重要)第一种响应为 OKAY,当一笔数据可完成传送时,S 会响应以 HREADY 为 1,且 HRESP[1:0] 为 OKAY;另外 S 也会在必须入额外延迟时 (HREADY 为 0),但未决定出何种响应方式时,作出 OKAY 的响应;
- 第二种种的响应方式为 ERROR,这种响应会在 M 所要求传送的数据发生错误时发生,而这种错误常常出现在 M 试图去存取一有读或写的保护机制模块,如 M 试图在只读存储器来写入数据。
- 第三种响应方式为 RETRY,此种响应会在 S 无法立即完成此笔数据传送,希望 M 重新传送此笔数据(了解)
- 第四种 S 响应模式为 SPLIT,这种方式的响应跟 RETRY 相似,都是发生在数据未能完成传递时。最大的不同是仲裁器在这两种信号响应之后,选择 M 时所使用的权位算法不一样。如为 SPLIT 响应,仲裁器只允许其它 M 来对 S 作存取的动作,即使要求数据传送的 M 比当前 M 的优先权位来的低,也就是说仲裁器不会选择当前的 M 来进行数据传送;如果 S 响应的是 RETRY,那么仲裁器会用一般的权位算法去找出当前发出数据传递要求权位最高的 M 来进行数据传递。(了解)
4.3、AHB Arbiter(要会画)
部分信号释义:
- 上图仅仅以 1 个 Master 来示意 AHB Aribiter,并不是说只能有 1 个 Master。AHB 总线默认可以挂载 16 个 Master,当然我们也可以通过修改位宽达到挂载更多 Master 的目的!
- 更多的还是关注 HUBUSREQ 是哪个 Master 过来的,然后对应给仲裁输出 HGRANT。相当于 HBUSREQ 和 HGRANT 相互之间进行握手,完成仲裁的控制。
4.4、AHB Decoder(要会画)
部分信号释义:
- Decoder 的作用就是输入 HADDR,然后根据 Slave 的空间划分,进行第一级译码操作。HSELx 分别对应一个 Slave。
- Decoder 的 RTL 实现就是通过
if...else
或者case
AHB 总线无论是在实际项目开发中还是在 IC 岗位面试中都常打照面,可以算得上是一个基础且高频的知识点了,所以拿下 AHB 自然义不容辞。本文意在摒弃 AHB 协议中的繁文缛节,化繁为简,将作者认为的 AHB 重点知识进行了提炼和梳理,并为 AHB 四大组件和基本传输时序制作了通俗易懂的图解说明。希望通过本文,可以帮助读者一举攻克 AHB。
SystemVerilog 项目实践之 AHB-SRAMC(5)(APB 协议基本要点)_apb 能不能 adc
- APB 信号介绍
- APB 传输时序
- AHB 与 APB 的区别与时序转换
- 不同 IP 之间的互联
2.1、APB 与 AHB 对比
AHB 主要用在高速高性能的外设中,而 APB 则主要用来挂载低速外设。
在 APB 上挂载的外设大都是 Slave,没有 Master,即被动接收数据的外设。
理解好了 AHB 总线之后,学习 APB 自然不在话下。好了,废话不多说,速速进入正文。
2.2、APB 信号介绍
信号名称 | 信号描述 |
PCLK | APB 总线时钟 |
PRESETn | APB 复位 |
PADDR[31:0] | APB 地址总线 |
PSELx | APB Slave 选择信号 |
PENABLE | APB 使能信号 |
PWRITE | APB 总线传输方向 |
PRDATA | APB 读数据总线 |
PWDATA | APB 写数据总线 |
注:APB 信号可结合 AHB 信号理解记忆。
2.3、APB 信号释义
- PADDR[31:0]
- 地址总线,由设备总线的 bridge 单元驱动
- PSELx
- 从译码器来的信号,到某一个总线从设备 x
- PENABLE
- 用于在设备总线上把所有访问按时间阶段进行
- PWRITE
- 高电平:写
- 低电平:读
- PRDATA 和 PWDATA
- 最多 32 位宽
2.4、APB Slave 地址译码
- AHB-APB Bridge 我们可以将其理解成 AHB Slave
- 上图中黑色部分是 Default Slave
- 地址译码是一级一级的
2.5、APB 互联示意图
- Bridge 作用是 AHB 到 APB 的时序转换
2.6、APB 时序(重要)
2.6.1、写传输
- APB 相对 AHB 来讲没有流水,每个命令固定至少 2 个时钟周期完成!
- APB 分为两个阶段,第一个阶段是
SETUP
阶段,只有一个时钟周期。此时PSEL
信号为高,PENABLE
信号为低。可类比 AHB 中的地址传输阶段! - 第二个阶段是
ENBALE
阶段。此时PSEL
信号为高,PENABLE
信号为高。读 / 写数据信号有效,可类比 AHB 中的数据传输阶段!
- 上述时序仅仅是 AMBA 1.0/2.0 的时序,固定只有两拍。升级到 AMBA 3.0 后可以利用 HREADY 扩展
ENABLE
阶段,而SETUP
还是一个时钟周期。
2.6.2、读传输
- 读跟写的最大差异在于
PWRITE
信号,此时该信号为低。
- 上述时序仅仅是 AMBA 1.0/2.0 的时序,固定只有两拍。升级到 AMBA 3.0 后可以利用 HREADY 扩展
ENABLE
阶段,而SETUP
还是一个时钟周期。
2.7、APB Bridge
- AHB 是流水的,对于 Bridge 来讲,主要作用是将流水打断,即把 AHB 的时序转成 APB,如果 AHB 是流水的话,就会通过这个 Bridge 来打断!
- 主要通过
HREADY
信号来将流水打成两拍。
- APB Bridge 还有个功能是用来做一个二级译码
2.8、APB Bridge FSM(状态机)
2.9、APB Slave 框图(接口信号,需要会画)
- Control 信号较 AHB 要少很多哦!
- ABMA 3.0 支持
PReady
信号哦~!
2.10、APB 到 AHB 的时序转换 - 读
- 上图是 AHB 读取 APB Slave 的时序操作,可以看到通过
HReady
信号将流水操作进行了打断 T1-T2
之间HREADY
为高,通过HADDR
传送地址信号,通过HWRITE
为低,传送读控制信号。T2-T3
之间HREADY
为低,打断 AHB 流水的读操作。同时,APB 的PSEL
为高,PENABLE
为低,APB 进入SETUP
阶段,读取地址和读控制信号。T3-T4
之间,APB 的PSEL
为高,PENABLE
为高,APB 进入ENABLE
阶段,通过PRDATA
读取 APB Slave 的数据。同时HREADY
为高,将读取到的 APB Slave 数据,返回到HRDATA
。- 至此一个读操作完成。
PRDATA
是可以直接送给HRDATA
(在同一拍),如果想要HRDATA
打一拍的话,可以在 APBENABLE
阶段也将HREADY
拉低,这样HRDATA
就会晚于PRADTA
一拍了。
3.1、通信方式
- CPU (Master) <–> IP (Slave)
- IP(Master) <–> IP (Slave)
3.2、Memory Mapped IO
- 每一个从设备都占用系统中的一段地址空间
- 所有的从设备都是可寻址的
- 寄存器 / 存储器都是内存映射方式访问
- CPU/IP 读写其他 IP 的数据类似于读写存储器
3.3、IP 间的通信互联
- 主设备被 arbiter grant 之后,可以访问总线上的所有从设备
3.4、 一个 IP 可以可以同时拥有主设备接口和从设备接口
- Master 去外读写数据
- Slave 作为寄存器配置
3.5、CPU 与 IP 之间的通信
- CPU 总是作为主设备
- IP 总是作为从设备
- IP 可以发出一个中断请求
- 只有 Slave 接口的 IP,要想主动通知 CPU 就可以通过中断的方式
- 中断里面的信息不能太多
- CPU 进入中断模式,由 interrupt service routine(ISR)来处理中断
- AMBA 简介
- AMBA2.0:AHB、ASB、APB
4.1、AHB
- AHB 的组成部分
- AHB Master、AHB Slave、AHB Aribiter、AHB Decoder
- AHB 信号
- HCLK、HRESETn、HADDR、HTRANS、HWRITE、HSIZE、HBURST、HWDATA、HSELx、HRDATA、HREADY、HRESP
- AHB 传输的两个阶段
- 地址周期、数据周期
- 当前传输的状态 HTRANS
- IDLE、BUST、NOSEQ、SEQ
- 猝发传输类型 HBURST(了解)
- SINGLE、INCR(如何开始一次新的 INCR 传输?)
- Burst 传输不可跨越 1K 边界
- HSEL:由 AHB Decoder 通过地址映射给出
- AHB Slave 响应信号
- HREADY 传输完成、HRESP 传输响应(OK、ERROR、RETRY)
- AHB Slave 短时间无法响应(HREADY)?长时间无法响应(HRESP)【实际使用无法界定什么叫短时间,什么叫长时间,故用的不多!】
- 32 位大小端数据总线的有效字节
- AHB 仲裁信号(了解)
- HBUSREQ、HGRANT、HMASTER
- 主设备 x 可控制总线的条件
- AHB Master、AHB Slave、AHB Arbiter、AHB Decoder 的接口信号
- AHB-Lite
4.2、APB
- APB 的组成部分
- AHB2APB Bridge、APB Slave
- APB 信号
- PCLK、PRESETn、PADDR、PSEL、PENABLE、PWRITE、PRDATA、PWDATA
- APB Slave 的地址映射
- APB 传输(AMBA 1.0/2.0)
- Always two cycle transfer:Setup cycle、Enable Cycle
- No wait cycle and response signal(AMBA 3.0 是有的)
- APB Bridge 和 APB Slave 的接口信号
至此 AMBA 协议中的 APB 总线理论知识便介绍完了,APB 较 AHB 最大特点就是没有流水操作,且 APB 在 AMBA 2.0 中,命令的执行固定两个时钟周期。通过本文的介绍我们也不难发现,APB 和 AHB 之间很多信号都类似,且 APB 较 AHB 少了许多控制信号,所以只要理解了 AHB,APB 自然不在话下。后面我们将通过 AHB-SRAMC 实战项目,继续深入理解 AHB 和 APB。
SystemVerilog 项目实践之 AHB-SRAMC(6)(AHB-SRAMC SVTB Overview)_systemverilog 验证
- AHB-SRAMC 验证计划
- AHB-SRAMC 验证平台的架构图
- AHB-SRAMC 验证平台的代码目录
- 如何跑一个简单的仿真
- 编写 Makefile 编译代码并且跑仿真
- 如何利用波形进行调试验证平台
- 如何利用 VSIM 调用波形文件
- 通过查看 interface 上的信号,确认激励是否正确
- 通过查看 interface 上的信号,确认响应是否正确
- 验证目标
- RTL VS Specification
- 针对 Specification 中的 Feature 去分解测试点(Test point)构造测试用例(Test case),而后去验证 RTL 是否满足 Specification 的要求。
- Code Coverage:line,interface toggle,(FSM,Expression,Path)【客观】
- 通过覆盖率,来衡量我们的验证进度
- Function coverage【主观】
- 自己去建模,自己去建立 cover group,然后针对要覆盖的点去写 cover point
- 完备性、正确性、协议符合型、容错处理
- 完备性要求我们一定要在 Specification 基础上将 Feature 分解全!
- 正确性要求我们构造的用例需要真 pass,整个环境的 check 要比较全面
- 协议符合型要求我们要符合协议,在该项目中就是 AHB 协议了
- 容错处理这个异常处理场景也需要去考虑,如何构造异常场景包(用例)
- 如:地址 addr 和 size 要对齐,假如 size 是 16bit,那么地址可以发 0 或者 2,不能发 1 或者 3。这个容错处理就是讲,如果发了 1 或者 3,不能让我们的总线挂死!这个也要作为 Feature 的测试点列出来!
- 验证语言
- SystemVerilog
- 验证平台架构
- 验证策略
- 覆盖率驱动的验证策略
- 白盒验证策略
- 激励
- 定向测试(极大、极小、边界跳转空间等)
- 带约束的随机化验证策略
- 基于断言的验证策略(测试内部信号跳变)
- 功能点划分(根据 Features 来分解测试点 testpoints,根据测试点再来构造测试用例 testcases)
- Features
- testpoints
- testcases
- 如:No.1 testcase:把 SRAM 的地址空间全部写 1,然后再读全部是否为 1
- No.2 testcase:把 SRAM 的地址空间全部写 0,然后再读全部是否为 0
- No.3 testcase:向 SRAM 中写 8bit 的数
- No.4 testcase:向 SRAM 中写 16bit 的数
- No.5 testcase:做一些随机…
- …(这里仅仅举例,Testcase 没有固定模板,每个人可能分解出来都不一样(思路、方法),但最终我们是要通过覆盖率来得到一个验收。)
注:当然此处的架构是原来的基础上简化的,我们实际使用会该其基础上再添加一个 agent 组件。
- data modeling 就是我们的 transaction,即我们要发的数据内容。如 AHB 的 transaction 就包含:HSEL、HWRITE、HADDR、HWDATA…(定义一个 calss,并将其定义为一个 rand 随机数)
- transaction 产生之后,便会在 geneator 产生具体的数据。geneator 的主要作用是分各种场景,如:write32(Addr, Data),其中 Addr 和 Data 由 Testcase 来告知,generator 收到 write32 的命令后,就会把 transaction 中的一些信号赋值:
tr.hsel = 1'b1; tr.haddr=Addr; tr.trans=2'b10; tr.hsize=2'b10;
。除了 write32 的命令,当然还会提供 read32、write8 等命令。generator 就要提供对 SRAM 操作的各种场景的接口,如何去用这些接口,是 testcase 来决定的。就像之前所讲,testcase 就像音乐指挥家,generator 里面就有很多乐器了,比如鼓手(write32)、吉他手(read32)、钢琴等,要去演奏一首歌曲时,什么时候鼓手动,什么时候吉他手动,都是指挥家(testcase)决定的。所以什么时候去用 write32 这些命令是 testcase 告诉他,告诉它之后,会根据 wirte32 的功能去把要发的数据值给填好,然后再通过 mailbox 传到 driver。
- 当然本项目实际的架构,会在 generator 和 driver 之间加一个 agent,agent 除了能接收 generator 的数据并传送到 driver,还可以将数据传送到 scoreboard,如下图所示。
- generator 会提供各种场景的数据产生方式,至于产生方式在用例中怎么用,是 testcase 来决定的,testcase 会例化整个 Environment。整个 hierarchy 最顶层是 top,top 下有多个 testcase,如:testcase1、testcase2…。每一个 testcase 就会例化同一套 ENV 代码,ENV 能支持多种 testcase。每种 testcase 去调用 generator 里面的场景的函数是不一样的。
- driver 的作用就是当 tr 给过来之后,按照 AHB 协议传输。产生数据的时候地址和数据同时产生,但是在 driver 的时候会先一个时钟周期发地址,再到下一个时钟周期发数据。
- 左边的 monitor 会把激励数据采集进来,并送到 scoreboard 去做一个 check(送给 Reference Model 做 Gold 模型输入的)。 右边的 Monitor 是采集的结果,并把结果送到 scoreboard 做一个自动化的比对。
- reciver 一般是没有的
- coverage modeling 一般是指 function coverage
- 一级目录
- ahb_sramc_svtb
- 二级目录
- doc rtl verif
- RTL 就是架构图中的 DUT
- 三级目录(verif 展开)
- agent env sim tb tests
- env 包含:Transaction、Generator、Agent、Driver、Scoreboard
- tb 包含:最顶层 top 的 tb 文件,还有就是 interface
- tests 包含:各种 testcase
- sim 包含:不会放. sv 文件,一般放 Makefile 脚本,启动验证;还会放 file list 文件
当然它这个验证平台的目录架构有点模仿 UVM 的手法,UVM 会把 generator、driver、monitor 这几个组件包裹在一个叫 agent 的组件中。当然我们做的话,就是按照 SystemVerilog 比较典型的 calssic 的去做。故我们实际去做的时候,三级目录中是每个 agent 的!
- 第一步,根据 ahb_slave 接口信号,编写 ahb_slave_interface
- 第二步,根据 ahb_slave 输入和输出接口,进行数据建模(Transaction)
- 根据 interface 来产生数据包 Transaction
- 第三步,编写数据生成模块 generator
- 不同的场景对应的 Transaction 数据不一样,在 generator 中将各种 scenario 写出来,产生不同的 Transaction
- 第四步,编写 agent 模块,仅仅是一个数据转发的功能
- 第五步,编写数据处理模块 driver
- 第六步,编写 monitor 模块,不然 scoreboard 无法比较!
- 第七步,编写自动比较模块 scoreboard(在这之前会)
- 第八步,根据 Specification 和接口信号,编写覆盖率模型(看覆盖情况,去增补用例)
- 第九步,编写测试用例 testcase
注:环境要能够进行 testcase 的扩展,ENV 不变的情况下。
- 编写 AHB-SRAMC 功能验证计划
- 构建 AHB-SRAM 控制器的验证平台目录结构
- 在 Linux 服务器上建立 testbench 的目录结构
- 如何利用 SystemVerilog 语言一步一步的构建 testbench?
- 如何利用带约束的随机化方法编写 testcase?
- 对比 AHB 协议和波形文件,检查 AHB Slave 接口信号是否正确?
- 如何利用 Makefile 调用 Questasim(VCS)运行仿真环境
- 如何利用 Questasim(VCS)生成和仿真波形?
注:通过本文的学习,可能只会可以回答前两个问题,不过不要紧,我们继续往下学习,回头再看这些问题就会一目了然!
注:一个一个模块去调试,这里以 Questasim 为例,后面实际例子以 VCS 进行详细演示!
- vlib work
- 创建一个 library
- vlog -sv -f rlt.f
- 首先编译 RTL 设计代码,确认 RTL 代码没有编译问题
- vlog -sv -f rtl.f …/…/agent/ahb/ahb_slv_if.sv
- 再增加编译自己编写的 interface,其中的文件使用相对路径(相对于 sim 文件夹)
- 确认自己编写的 interface 没有语法错误
- vlog -sv -f rlt.f …/…/agent/ahb/ahb_slv_if.sv …/…/agent/ahb_ahb_slv_pkt.sv …/…/agent/ahb/ahb_slv_generator.sv …/…/agent/ahb/ahb_slv_driver_vase.sv …/…/agent/ahb/ahb_slv_driver.sv
- 依次编写 packet(数据建模)、generator、driver 等分层的 SVTB 功能模块
- 并对每一个功能模块进行编译,并进行编译和仿真
- 编写 test 和 tb_top 模块,并进行编译和仿真
- 通过查看 DUT 的端口的波形,确保所有的输入没有 x 或者 z
- 检查 DUT 的接口信号的输入是否是正确
8.1、输入端口有 X(出现红色)
- 仿真最前面出现红色的信号,而后恢复正常,这样的信号是正常的。但是一直都是红色就有问题了,比如图中的 haddr 信号。
- DUT 的输入信号 haddr 是 x,所有输入不正确,即 driver 的信号没有通过 interface 驱动到 DUT 的接口,因此需要检查 driver 是否正确动了 interface,然后再检查 interface 是否正确跟 DUT 进行连接。
8.2、输入端口有 Z(出现蓝色)
- DUT 的 hburst 信号出现了 z,点击信号前的 “+”,可以看到 [0] = 1’’h0,[1] 和 [2] 为 z,说明信号的驱动的位宽不正确,即 DURT 是 3bit 输入信号,驱动是 1bit 信号!
- 修改完代码,重新跑仿真时,需要先把整个环境清除干净!
make clean -f Makefile.qs; make all -f Makefile.qs
8.3、hrdata 为什么是红色的 x?
情形一:
- 原因是 sram 默认情况没有初始化,直接读 sram 的信号的话,就会读出 x
- 因此正确的处理方法是:首先对 sram 进行初始化,然后再进行读操作
情形二:
- Hsize = 3’b000(8bit);3’b001(16bit);3’b010(32bit)
- 如果只读了 8bit 数据,其他 24bit 数据还是 x 态;同理如果只读了 16bit 数据,其他 16bit 数据还是 x 态
8.4、调试经验(实践中体会)
- 将 DUT 的所有输入和输出端口全部加载到波形窗口,检查 DUT 的所有输入接口是否有 X,如果 DUT 的输入端口存在 X,所有有错误!
- X 可能是 input 信号 floating 导致的,就是 input 接口没有驱动
- 将 DUT 的所有内部信号加载到波形窗口,检查是否存在 x,如果存在 x,可以有问题
8.5、在波形图中双击左键的效果
- 左键双击波形信号,会把对应的代码(source code)弹出来(不推荐)
- 左键双击信号名,会把对应的属性(properites)弹出来
8.6、将 source code 中的信号添加到波形中
- 左键选中某一个信号,然后组合键 ctrl+w(实用 )
8.7、查找信号的驱动
SystemVerilog 项目实践之 AHB-SRAMC(7)(AHB-SRAMC SVTB Code 上篇)_ahb_sramcd svtb
通常基于
systemverilog
的验证平台主要包括以下几个部分:- 最顶层
Testbench_Top
,包括: - 1、
DUT(design under test)
- 2、TEST 验证平台
- 主要包括 env 环境,包括:
- transaction 数据包
- generator 数据发生器
- driver 数据驱动器
- monitor 采样
- scoreboard 比对器
- coverage 覆盖率收集
- 3、二者之间的 interface 接口
注:基于 SV 的验证平台中,当数据由 agent 发送去 Scoreboard 时,在激励前就不再需要用(左侧)monitor 去采集进入 DUT 的数据,但由 DUT 送出的数据依然会由 monitor 采集,送入 Scoreboard,然后进行比对。
4.1、接口 interface
第一步:进入
./svtb_sram_ahb_new/verif/tb
文件夹,编写接口文件ahb_slv_if.sv
!ahb_slv_if.sv
clocking interface
主要是为了让我们的 interface 信号跟我们的 DUT 信号达到同步。它们本来是同步的,在仿真模型上也要达到同步。不然可能会出现,仿真给出的时序跟 DUT 电路时序不是同一个时序,设计上 Master 和 Slave 就是一个时钟域的,仿真的时候也要按照这样的方式去仿真!
- modport 可以防止我们把信号接反
- 每编写完一个文件后,最好最一些调试(主要是检查语法问题),以保证小模块是正确的。
下图是使用 Questasim 进行编译,检查是否有语法错误,编译命令:
vlog -sv ahb_slv_if.sv
VCS 编译该模块,会有如下图错误提示,故我们编译
interface
模块一般用 Questasim!注:后文的模块如无特殊说明,都将使用 VCS 进行编译,单模块编译目录一般在./svtb_sram_ahb_new/verif/env下。
4.2、数据包 transaction
第二步:进入
./svtb_sram_ahb_new/verif/env
文件夹,建立我们的数据模型transaction.sv
!transaction.sv
- 当然我们并不是把 interface 所有信号都放到这个里面发,因为有些信号是固定接死的,所以没必要采集去看它的覆盖率或者发送的时候去做随机的处理!
- 后面我们要传的数据,都是通过这个 class 去实例化(它仅仅是个模型),一般设置名字为
tr
!然后通过generator
去产生具体的数据,即generator
根据我们的场景(scenario)来产生addr、data、write....
(如write32...
)
- 我们写 build 更多的还是为了后文介绍 UVM 做铺垫。另外,我们通常将 new 和 build 定义为 function,将 run 定义为 task。关于 function 和 new 的区别回顾,参考:【数字 IC 验证快速入门】15、SystemVerilog 学习之基本语法 2(操作符、类型转换、循环、Task/Function… 内含实践练习)
下图是使用 VCS 进行编译,检查是否有语法错误,编译命令如下:
4.3、数据包生成器 generator
第三步:进入
./svtb_sram_ahb_new/verif/env/generator
文件夹,编写数据包生成器generator.sv
!- 所有的不同用例,用到的 generator 都是同一个,但是不同的用例(Testcase),发的激励可能不一样(调用的函数不一样),就需要参数化的方式把不同命令传进来,告诉 generator。那么就可以针对不同命令(
write_data32/write_data16...
)产生不同的数据,这就是可重用的思想,也就是说所有的不同用例,用到的 generator 和 env 的代码就只有一套。
- 一个 case 不一定是把场景都用完,可能只是用到一部分场景。testcase 会调用这里面的场景。generator 相当于乐器,testcase 相当于旋律。
- 初期调试的时候不太可能用
all_random
,因为你自己发的什么东西都不知道,那么你去看你的波形是不是对的你也看不出来。
generator.sv
- 一个事件必须有两个操作,触发操作和等待操作,通常是等待在前,触发在后
Q:为什么写数据的时候随机了,读数据的时候还要随机呢?
- A:读数据通常是我们从 sram 里面读出来的,generator 里面 hrdata 通常用不上,但是为了完整性还是写上去了。另外,rand 类型的数据仍然可以给他赋予一个确定的值。并不是说赋成了 rand 一定就是随机的。是否赋随机值是根据要求来的
SystemVerilog 项目实践之 AHB-SRAMC(8)(AHB-SRAMC SVTB Code 下篇)
- monitor 组件
- scoreboard 组件
- 验证环境搭建总结
上一节,我们编写了 ENV 环境中的 Transaction、Generator、Agent、Driver 组件,并通过波形查看测试用例是否正确。但是用波形看结果是费时费力的,因此本节将会去做一个自动化比对,把输入 DUT 的激励和输出 DUT 的响应采集起来,然后再放到 scoreboard 里面做一个自动化比对。
4.10、采样模块 monitor
第十步:进入
./svtb_sram_ahb_new/verif/env/monitor
文件夹,编写采样模块 monitor.sv
!- monitor 采集模块需要将采集的数据做时序还原处理,使其地址阶段与数据阶段同步,以满足 SRAM 的时序要求,然后再将其打包放入邮箱发送至 scb。
monitor.sv
Q:为什么 interface 里的 haddr 要经过 haddr_1d 再传递给 tr, 而 hwdata 可以直接传给 tr?
- A:AHB 的特点,一个操作需要两个周期完成,第一个周期是地址周期,第二个周期是数据周期,时序协议所规定的,地址和控制信号都在数据前面一个时钟周期,从 interface 过来的信号,肯定按 AHB 协议来做,但是环境内部是没有时序,tr 一个数据包,包含所有内容,是不具备时序的。所以如果把对应的数据和命令都放在一个包里面的话,相当于做一个同步的调整,放在同一个周期才行。因为地址要做到和数据同一拍,就要比数据晚一拍才行。
- driver 和 monitor 是在同一个层级的,这个项目只涉及到一个 monitor,我们现在只会从 ahb 接口这采集我们的数据。Agent 把数据传给 scboard, driver 把 tr 转成 DUT 接口时序。Agent 可以让组件层次的管理简单点
- 1<<2 左移两位
- 命令是 master 发给 slave 的,数据是 slave 到 master 的,在 interface 去采集就可以同时去处理。如果是分离,那么命令是在 generator 去采集,数据是在 interface 采集的,那么时序控制就复杂点,相当于 scoreboard 先收集到读命令,数据什么时候过来不知道,那么 scoreboard 设计就很复杂了。环境不要和底层的时序耦合在一起,这也是为什么要在 interface 去采集的原因
使用 VCS 进行编译,检查是否有语法错误,编译命令如下:
monitor 检测完之后根据数据流就把数据送到 scoreboard
4.11、比对模块 scoreboard
第十一步:进入
./svtb_sram_ahb_new/verif/env/scoreboard
文件夹,编写比对模块 scoreboard.sv
!- 计分板 scoreboard 会将从 agent 发来的数据与由 monitor 收集的 DUT 输出数据进行一一比对。比对方法回顾可参考文章:简单全加器验证—Testbench。
- monitor 完成之后再来写我们的 scoreboard。在 scoreboard 里面会建立 reference model,地址深度是 64k,理想的 ram 是一个数组的结构,定义成 logic 类型,初始值是 x
scoreboard.sv
- 1、自动化比对的环境的搭建。在 scoreboard 里面做一个 check,相当于从 mon 里面 get 到的数据,一方面如果是写操作就放到 gloden 的 ram 里面,另外一方面如果是读操作,就把读数据和从 gloden 里面读出来的数据做一个比对,如果能比上就认为 ram 的行为和 gloden 的行为是一样的,如果比不上就认为有问题。
- 2、generator 还可能发送一些无效的命令,所以要判断 tr 是不是有效的,有效才对 ram 进行操作。无效就不操作。采集的数据 hsel 为高,同时 htrans 的第一个 bit 为高,即 2‘b10 或 2’b11,就认为是有效的。
- 3、然后针对是命令的读还是写做不同的处理, tr.hwrite 为高是写操作,就把数据写到 sram,写 sram 是根据命令的 hsize 和地址的低两位来判断是写 8 位,16 位还是所有的 32 位,因为一个 ram 的地址空间是 32 位。
- 4、同时地址要对齐,所谓对齐就是说地址要是常数的整数倍,10 代表 size 的长度是 4 个 byte,地址的最小单位是 1byte。如果长度是 4 个 byte,那么地址必须为 4 个 byte 的整数倍,4 个 byte 的整数倍那么地址只能是 0,4,8,c。要是 0,4,8,c,是 4 的整数倍,那么对应的地址的低两位必须要是全 0。否则不匹配就打印一个 error 出来,地址和 size 不匹配,同时会把地址单元赋一个 x 值进去
- 5、这块跟 RTL 不一样的是,因为我们是 gloden 模型,所有我们没有分 bank,没有物理实现,只是实现一个逻辑功能,只要数据能写进去就行。低功耗更多的是用 assertion 来做检查,而不是功能。这个功能更多的是对逻辑行为进行检查仿真。
- 6、72,73 行 4’b01_00 和 4’b01_10 是针对 size 是 0,1 的时候,这时候是两个 byte,地址要为两个 byte 的整数倍,只能是 0,2,4,6,8,c 这种。也就是说低两位要么是 00,要么是 10。00 的话是只写 sram_gld 对应地址空间的低的两 byte[15:0],10 代表地址是 2,就写高的两个 byte 即 31 到 16。
monitor 和 scoreboard 弄完了,只是个独立的组件,要让整个 env 跑起来就需要在 env 里面把这两个组件加进来
4.12、其他组件修改
4.12.1、environment.sv 修改
主要增加的几个地方如下:
完整代码如下:
environment.sv
4.12.2、Makefile 修改
主要增加的几个地方如下:
完整代码如下:
在上一小节,我们是通过看波形来判断结果与预期是否相符,本节通过 monitor 和 scoreboard 实现了自动化的比对,如果与预期相符,便会在
rslt.log
中输出TEST PASS
字样。我们直接在在终端输入
make
进行 testcase0 的编译,rslt.log
输出内容如下:可以对比波形查看,与预期相符,故测试用例通过!
到现在为止我们只构造了三个用例,怎么证明规格完了呢,就需要增加覆盖率 (代码和功能) 来检验
整个验证环境的搭建可分为三步:
- 第一步:就是把 driver,generator 等产生激励的组件给做好,然后把基本的简单的测试用例也给规划出来,这时候就可以调试一下环境是不是 ok 的,波形怎么样。从波形上看激励和预期是一样的那么激励就 ok 了
- 第二步:是做自动化比对,写我们的参考模型
- 第三步:就是写 coverage 模型,收集到 100%,整个验证才结束,对于大型的 soc 还要不停的去跑随机
SystemVerilog 项目实践之 AHB-SRAMC(9)(AHB-SRAMC Debug 技巧)
Run 仿真主要分为两部分:
- 第一步是编译,检查所有写的代码文件的语法错误,同时没有语法错误时,就会把这些代码链接起来,因为这些代码从结构上来见是分层次的,最终验证的话只有一个顶层 top,其它的是不断封装和连接的。
- 第二步是运行仿真,真正的仿真就会去写很多的 run,所谓 run 就是隔一个时间单位去做什么事情。第一步语法检查正确并不代表第二步运行仿真完全没有问题。以前写的 simulate 比较简单,可能就是一个 initial 块,一般有错也能跑出来。但是随着仿真复杂程度的增加,有很多线程可能是并行的,如果这些线程之前相互有一些等待,或者连接没有做好,顺序关系没做好时,就会导致 simulate 卡死。
本讲主要看一些常见的 bug(根据 log 文件判断快速定位定位问题),从而掌握一些验证工程师必会的 Debug 技巧!
2.1、错误 1 示例(语法错误)
问题分析:“
Following verilog source has syntax error
” - 说明具有语法错误;“token ‘transaction’ should be a valid type. Please declare it
.” - 说明 transaction 定义没有被找到,原因可能是没有添加 transaction 编译文件,也可能笔误写错了名字,我们一一排查。接着看下面 log,提示是在./generator/generator.sv
的第 6 行不能识别transaction tr
。首先找到我们自己写的 transaction 的定义,对比定义和 generator.sv 声明的名字,发现是一样的,所以可以排除笔误。接着检查编译选项是否添加 transaction 文件,果然我们编译时只写了 generator.sv,所以当然找不到 transaction 了,加上即可编译通过!当然上面只是举了可能的原因,实际的工程操作中,具体情况需要具体分析,并没有什么灵丹妙药包治百病,我们只能通过蛛丝马迹去猜测可能的错误,然后再去验证。对于笔误,我们通常有一个技巧就是通过
shift+*
高亮的方法去快速定位。2.2、错误 2 示例(语法错误)
问题分析:这个 EDA 工具直接将问题定位在了
ahb_sramc_svtb_top.sv
文件的第 13 行,指出ahb_sram_if
这个接口示例是不能被识别的,通过shift+*
高亮的方法,我们可以发现,我们与上面定义的 interface 实例化名称缺少了字母c
,更改为ahb_sram_test test(ahb_sramc_if)
即可解决!我们不仅要能发现错误,还要理解为什么应该是那样。如上述笔误错误,虽然是很小的错误,但是并不是改完之后就完事大吉了,对于 AHB-SRAMC 项目的练习,我们要时刻想起验证环境的架构图,知道接口文件是用来连接我们的 Testcase 和 DUT 的,对应到代码就是
ahb_sram_test
模块(Testcase)和sramc_top
模块(DUT),所以接口的实例化名字要保持一致。故,我们一定要深入理解好代码结构,理解其内涵的逻辑层次。注:所谓代码结构不仅要在架构上有清晰的认识,具体到每一行代码也要知道是什么意思?与其他行的代码关系是什么样的也需要知道!
代码结构不清楚的话,可以通过运行 Makefile 中的
dve_wave
来查看,即运行命令make dve_wave
,代码结构如下图:- 概览图
- 展开之后
2.3、错误 3 示例(逻辑错误)
语法正确之后,跑仿真也未必一定可以成功!
比如在 scoreboard.sv 中的 check,会重复你的发包个数,每次会等待 monitor 到 scoreboard 的数据包(对应代码
mon2scb_mbx.get(tr);
)。那么假如 monitor 到 scoreboard 之间邮箱连接没有连的话(邮箱 get 到才能往下执行),那么此时仿真一直会在这等。monitor 到 scoreboard 它们之间连接,是在environment.sv
中操作的。假如monitor.sv
中的mon2scb_mbx.put(tr);
被注释了,即 monitor 没有 put 到 scoreboard,那么整个仿真很有可能就一直卡住了。运行一下,效果如下:上图便是一直在某个地方等待了,
ctrl+c
强制退出等待,然后再输入exit
退回到正常的命令行界面。如果不知道有这个 BUG,如何去 Debug?要学会去打印!
假设我们之前调试的 transaction、generator、agent、driver 等模块都是 OK 的,新增了 monitor 和 scoreboard 之后便出现上述一直等待的问题!首先,我们还是按照数据流一步一步去走,先去看看 monitor 从 DUT 通过 interface 采集过来的 transaction 是否正确(跟我们发出的激励是否一致),即在
monitor.sv
中加入如下打印语句:添加代码位置如下:
注:把 SV 学好了,UVM 就是小意思,因为 UVM 就是把 SV 的一些东西封装了!
增加打印信息后,运行
make
命令,效果如下:上述地址和数据打印信息与发送的激励一致,说明 monitor 从 interface 采集到的数据是正确的!接下来再在
scoreboard.sv
中添加打印信息,查看是否收到。(按照数据流的方向),添加代码如下:添加位置如下:
增加打印信息后,运行
make
命令,效果如下:只有 monitor 打印信息,没有 scoreboard 打印信息,由此可以推断出 scoreboard 没有收到,说明两者之间的数据流出了问题,可以依次检查下
environment.sv
的邮箱建立是否正确,monitor 是否进行 put 操作,scoreboard 是否进行 get 操作等等。一番排查下来不难定位到问题所在,对于我们这次情况是少了 put,正确排查后,再次运行,效果如下图:注:调试完毕后,记得在代码中屏蔽打印信息,方便后续 log 信息的查看!
至此整个数据通路便正常了!从上述常见错误中,可以看出要想快速定位到 BUG,首先要有扎实的 SV 语法基础,其次要知道整个验证环境的结构(从哪里采集数据,经过哪些组件,最后到了哪些组件)。这样如果数据流出了问题,可以一步一步通过打印信息的方式进行定位。因为 ENV 环境在波形里面是看不到的,我们只能看到 interface 到组件,所以我们需要学会巧用打印的方式去做问题定位。
注:VCS 可以自动建库(Library),但 Questasim 需要手动建库(Library),不然编译会出错,建议可以做成脚本的方式,选择用 vcs 还是 vlog 编译!
我们本节的目的不是为了 Debug 而 Debug,而是为了帮助读者建立一些 Debug 的思维,如上述错误示例 3 这种逻辑错误在实际开发中其实经常遇到,我们就是按照数据流的方式一步步去溯源从而找到问题的所在,这就是其中一种 Debug 逻辑思维!读者朋友一定要学会举一反三,多总结,多思考,这样无论什么项目,无论什么验证环境都能立于不败之地!
SystemVerilog 项目实践之 AHB-SRAMC(10)(AHB-SRAMC 项目总结回顾
一、AHB-SRAMC 项目介绍
本项目中的 SRAM 控制器具有较低的功耗和较小的面积,其一端连接 AHB 总线,另一端连接大小为 64K 的 SRAM 存储器,该存储器为单端口。本项目的 SRAM 控制器的作用就是实现 SRAM 存储器与 AHB 总线的数据信息交换。其组成结构示意图如下图所示:
注:RAM 通常可分为单端口 RAM 和双端口 RAM。其中双端口 RAM 又分为简单双端口 RAM 和真正双端口 RAM。对于单端口 RAM,读写操作共用一组地址线,读写操作不能同时进行;对于简单双端口 RAM,读操作和写操作有专用地址端口(一个读端口和一个写端口),即写端口只能写不能读,而读端口只能读不能写;对于真正双端口 RAM,有两个地址端口用于读写操作(两个读 / 写端口),即两个端口都可以进行读写。
SRAM 控制器设计大体可以划分为以下三个模块:
- ①、SRAM 控制单元
- ②、SRAM 存储单元(内嵌 MBIST 电路)
- ③、AHB 总线控制单元(含 AHB 总线的接口模块、地址路径和数据路径)
三大模块的详细代码参见上一篇文章。本项目的设计核心是 AHB 总线控制单元和 SRAM 控制单元。AHB 总线控制单元直接收来自外部的访问请求,并把这些信息转化为外部对 SRAM 存储器的数据存取请求。SRAM 控制单元直接与存储器相连接,主要的功能是将控制信号、地址信号、数据信号进行转化,并将其发送给 SRAM 存储器,进行实际的数据存取。地址路径可以分为地址译码路径和地址通路两部分,数据路径可以分为写数据通路和读数据通路。
1.1、AHB 总线控制单元(ahb_slave_if.v)
AHB 总线控制单元是 AHB 总线与 SRAM 控制器连接的接口,所有 AHB 总线传输过来的数据信号都必须经过总线控制单元的转换处理。否则,数据信号就不能被传送到 SRAM 控制器,就不能很好的实现 SRAM 控制器与总线之间的数据传输。这里的 AHB 总线控制单元在设计称为 slave interface。AHB 总线控制单元的接口图如下图所示:
图中左侧的数据信号为 AHB 总线传输到总线控制单元的信号,包括地址信号、控制信号、数据信号。图中右侧为控制单元反馈给 AHB 总线的信号。这些信号都是与 AHB 总线兼容的。当 HSEL 信号有效时,总线控制单元与 SRAM 存储器控制单元之间可以进行信息传输,实现对 SRAM 存储器的读写操作。总线控制单元的主要作用就是接收来自 AHB 总线的地址信息和数据信息等,将这些总线访问的指令信息处理后送到其他单元:将读写地址信息传送到地址路径,将写数据送到数据路径,同时接收数据路径返回的读数据。
1.2、SRAM 控制单元(sram_top.v)
SRAM 控制单元直接控制 SRAM 存储器进行存取操作,因此,SRAM 控制单元与 SRAM 存储器连接的接口信号也很重要。SRAM 存储控制单元和 SRAM 存储器的信号接口图如下所示:
SRAM 的工作原理很简单,SRAM 控制单元根据接收到的总线控制信号,将这些信号处理转化为 SRAM 存储器可以识别的信号,发送到 SRAM 存储器;之后,将经过地址译码的物理地址传送到存储器的地址总线,并将数据路径处理的数据送到 SRAM 存储器的数据总线。最后,SRAM 存储器进行相应的读写访问。如果是写操作,SRAM 控制单元的任务就完成了,SRAM 存储器已将数据信息按照要求写入。如果是读操作,SRAM 控制单元需要接收返回的读数据,将其送到数据路径,由数据路径将信息传输给 AHB 总线,最终实现总线对 SRAM 的读操作。
在本项目中,将 SRAM 控制单元作为顶层(模块名为 sramc_top.v),调用总线控制单元(模块名为 ahb_slave_if.v)和 SRAM 存储器(模块名为 sram_core.v)。
1.3、主要的传输路径
由于要实现 SRAM 存储器和 AHB 总线之间的数据传输,就要有地址路径和数据路径两个重要的组成单元。
地址路径的主要功能就是提供访问地址信息,在本项目中,地址路径的作用就是接收 AHB 总线的读写访问地址,并将这些信息传送到 SRAM 控制单元。当 SRAM 存储器处于无法访问状态时,地址路径会将地址信息暂时存放,直到对 SRAM 实现读写访问时,地址路径才会继续有效。地址路径有两个部分组成:地址译码单元和地址通路。
地址译码单元的主要任务就是将读写地址编译成 SRAM 存储器可以识别的地址。地址通路是在地址译码单元的基础上,实现对读写地址的缓冲,这是由 SRAM 存储器的读写基本传输特性和猝发传输特点所决定。
数据路径的作用就是实现 AHB 总线对 SRAM 存储器的正确访问。在项目中,数据路径的功能就是实现写数据通路和读数据通路。
写数据通路就是从系统内其他主设备向从设备写入数据必经的通道,它的作用是可以暂时存放数据信息。当有写操作要求时,SRAM 控制器检查写数据通路是否有空间,如果有就写入待写数据,如果没有空间,那么等待下一个周期。写数据通路使用 FIFO 来实现。
读数据通路和写输入通路相对应,数据从 SRAM 存储器返回到 AHB 总线也需要经过读数据通路。当 AHB 总线处于 BUSY 状态时,不能接受从 SRAM 存储器传输的数据时,就可以将这些数据暂时存放在读数据通路当中,当 AHB 总线处于 IDLE 时,这些数据传输到总线上面进行处理。也就是说读数据通路其实也扮演着数据缓冲的作用。在设计中,和写数据通路一样,也常使用 FIFO 实现。
二、结构框图
2.1、AHB_SRAMC 结构图(重点)
上面介绍了整体的设计思路,SRAM 控制器设计框图,如下两幅图所示。将 SRAM 存储单元部分设计分为上下两个 bank(block),bank0 包括 sram_bist0、sram_bist1、sram_bist2、sram_bist3 四个部分,地址范围是 0 到 31;bank1 包括 sram_bist4、sram_bist5、sram_bist6、sram_bist7 四个部分,地址范围是 32 到 63。
这种 设计方法的优势在于在运行的时候,如果选中 bank0,那么下面的芯片都没有片选中,因此,bank1 中的存储单元处于闲置状态,bank1 的内存功耗很低。同时,每个 bank 又分成 4 片(AHB 支持 8/16/32 位操作)。比如,在 0 到 32 位的空间,我们只取一个 8 位的操作,只选中 4 片中的一片,剩下的 3 片功耗都很低。在整个设计系统中,8 片 SRAM 只有一片被选中工作,其余的都未被选中,未被选中的 SRAM 功耗很低,片选中的功耗与没被选中的功耗会相差数十倍甚至上百倍,这样将会很大程度降低了功耗。
2.2、总线控制单元与 SRAM 控制单元结构图
DUT 代码使用 vivado 综合后的电路如下图所示:
图 1:sramc_top 模块综合后原理图
图 2:ahb_slave_if 模块综合原理图
图 3:sram_core 模块综合后原理图
注:vivado 综合后的电路原理图 PDF 可从这里下载:https://download.csdn.net/download/ReCclay/33193010
从上图 1 中可以看出,总线控制单元端口主要是控制信号和数据信号等。这一个模块的主要作用就是将总线的信号转化为 SRAM 控制单元可以识别的物理信号,进而实现读写操作的功能。总线控制单元的内部结构如上图 2 所示。
总线控制单元模块是设计中的重点模块,这一部分核心的代码在第三部分有详细的展示。由于 SRAM 存储单元采用的 8K*8 的设计方式,且每个 BANK 中包含 4 块 SRAM 存储单元。因此,每个 BANK 的位宽为 32 位,且 AHB 总线也支持 32 位的操作,在写数据时可以直接赋值,其中,片选信号是由高位译码产生的。
三、部分核心代码 (重点理解)
根据上面的结构框图,对电路进行设计。 顶层模块包含 AHB 总线模块和存储单元模块。其中,存储单元模块由 8 个子模块构成,每个子模块由一个 SRAM 存储单元和 bist 结构组成。
下面简单介绍一下总线模块的部分代码,实现的主要功能就是 AHB 总线与 SRAM 存储单元的数据传输。这一部分也说明了存储单元是如何进行片选的,正是由于采用了片选结构,电路整体功耗才比较低。
上面部分代码是与结构框图相对应的片选部分,这一部分是组合逻辑部分,主要是分成两个操作:数据从 SRAM 传输到 AHB 总线和数据从 AHB 总线传输到 SRAM 中。这一部分设计的意义在于只有一片 SRAM 工作,整体功耗较小。在时序逻辑部分,片选 hsel 信号,避免信号不停翻转,可以有效降低功耗。
注:如有遗忘,可参考《【数字 IC 验证快速入门】28、SystemVerilog 项目实践之 AHB-SRAMC(8)(AHB-SRAMC RTL Code)》
四、SystemVerilog Testbench 架构(重点)
基于 SystemVerilog 的验证平台如下:
如何一步一步编写 SystemVerilog Testbench,步骤如下:
- 1、根据 ahb slave 接口信号,编写 ahb slave interface;
- 2、根据 ahb slave 输入和输出接口,进行数据建模 transaction;
- 3、编写数据生成模块 generator;
- 4、编写数据代理模块 agent;
- 5、编写数据处理模块 driver,将数据驱动至 DUT;
- 6、编写数据采集模块 monitor,送至 Scoreboard;
- 7、编写自动化比较模块 Scoreboard,进行数据比较;
- 8、根据 specification 和接口信号,编写覆盖率模型 coverage;
- 9、编写测试用例 testcase;
- 10、编写 Makefile 脚本文件,运行仿真;
五、AHB-SRAMC 目录结构回味
六、一些想说的话
至此,AHB-SRAMC 项目基本落下帷幕。在该系列文章中,我们首先学习了 AMBA 总线,并着重研究了其中的 AHB-Lite 总线,为后文 AHB-Slave 这个 DUT 模块编写以及 AHB 总线通信打下了基础。接着我们就 AHB-SRAMC 的 Feature、Architecture 进行了学习,对于架构的深入理解,我个人觉得是非常有必要的,理解了架构才能提纲挈领抓起整个项目的核心,才能在后面的验证环境搭建中保持清醒的头脑。然后我们编写了 DUT 中的 AHB Slave Interface 模块,这个模块的理解对于后面验证环境的搭建也非常重要,值得读者深入研究。最后我们搭建了基于 SystemVerilog 的验证平台,主要包括:数据模型模块 Transaction,数据发生模块 Generator,数据代理模块 Agent,数据驱动模块 Driver,数据采集模块 Monitor,数据比对模块 Scoreboard。上述几大模块撑起了整个验证环境,每个模块也都有值得研究和思考的地方,这里篇幅所限就不一一展开。当然,项目最后还对覆盖率分析进行了详细的阐述,包括用例的构造及构造依据等。如果读者能独立认真地把这个验证项目研究下来,我个人觉得已经算是一只脚踏进了验证的大门。当然,后面我们还会学习 UVM,我个人理解 UVM 本质是封装了 SystemVerilog,然后加入了一些机制,当我们把 SystemVerilog 掌握透彻之后,UVM 假以时日也能轻松拿下。最后还需要声明的是,由于不少博文成文于深夜,不免困意来袭,思绪混乱,可能会出现部分行文啰里啰嗦的情况,还请各位读者谅解。由于个人精力有限,现无法及时修订,但在完成本系列文章后,笔者将逐篇文章进行修订润色。
- 作者:Conor
- 链接:https://www.xzhh.top/article/SV2023_2
- 声明:本文采用 CC BY-NC-SA 4.0 许可协议,转载请注明出处。