总线(bus)
一、AHB-Lite3
配置与实例化(Configuration and instanciation)
首先, 每次创建AHB-Lite3总线时, 都需要一个配置对象。这个配置对象是一个
AhbLite3Config
, 有以下参数:
参数名 | 类型 | 默认值 | 描述 |
---|---|---|---|
addressWidth | Int | HADDR的位宽(字节粒度) | |
dataWidth | Int | HWDATA和HRDATA的位宽 |
简而言之, 在SpinalHDL库中AHB-Lite3总线是如下定义的:
case class AhbLite3(config: AhbLite3Config) extends Bundle with IMasterSlave{
// 地址和控制
val HADDR = UInt(config.addressWidth bits)
val HSEL = Bool()
val HREADY = Bool()
val HWRITE = Bool()
val HSIZE = Bits(3 bits)
val HBURST = Bits(3 bits)
val HPROT = Bits(4 bits)
val HTRANS = Bits(2 bits)
val HMASTLOCK = Bool()
// 数据
val HWDATA = Bits(config.dataWidth bits)
val HRDATA = Bits(config.dataWidth bits)
// 传输回答
val HREADYOUT = Bool()
val HRESP = Bool()
override def asMaster(): Unit = {
out(HADDR,HWRITE,HSIZE,HBURST,HPROT,HTRANS,HMASTLOCK,HWDATA,HREADY,HSEL)
in(HREADYOUT,HRESP,HRDATA)
}
}
简单的使用样例:
val ahbConfig = AhbLite3Config(
addressWidth = 12,
dataWidth = 32
)
val ahbX = AhbLite3(ahbConfig)
val ahbY = AhbLite3(ahbConfig)
when(ahbY.HSEL){
//...
}
变式(Variations)
有一个AhbLite3Master变体。唯一的区别是没有
HREADYOUT
信号。当互连线和从端口使用AhbLite3
时, 这个变式应该只被master使用。
二、Apb3
简介
AMBA3-APB总线通常用于连接低带宽外设。
配置和实例化
首先, 每次创建APB3总线时, 都需要一个配置对象。这个配置对象是
Apb3Config
, 有以下参数:
参数名 | 类型 | 默认值 | 描述 |
---|---|---|---|
addressWidth | Int | HADDR的位宽(字节粒度) | |
dataWidth | Int | PWDATA和PRDATA的位宽 | |
selWidth | Int | 1 | PSEL的位宽 |
useSlaveError | Boolean | false | 指定PSLVERROR |
简而言之, APB3总线在SpinalHDL库中定义的方式如下:
case class Apb3(config: Apb3Config) extends Bundle with IMasterSlave {
val PADDR = UInt(config.addressWidth bits)
val PSEL = Bits(config.selWidth bits)
val PENABLE = Bool()
val PREADY = Bool()
val PWRITE = Bool()
val PWDATA = Bits(config.dataWidth bits)
val PRDATA = Bits(config.dataWidth bits)
val PSLVERROR = if(config.useSlaveError) Bool() else null
//...
}
简单的使用样例:
val apbConfig = Apb3Config(
addressWidth = 12,
dataWidth = 32
)
val apbX = Apb3(apbConfig)
val apbY = Apb3(apbConfig)
when(apbY.PENABLE){
//...
}
函数和运算(Functions and operators)
参数名 | 返回 | 描述 |
---|---|---|
X >> Y | 连接X到Y。Y的地址可以小于X | |
X << Y | 做与>>相反的操作 |
三、Axi4
简介
AXI4是ARM定义的高带宽总线
配置和实例化
首先, 每次创建AXI4总线时, 都需要一个配置对象。这个配置对象是一个
Axi4Config
, 它有以下参数: 注意:useXXX 指定总线是否有 XXX 信号。
参数名 | 类型 | 默认值 |
---|---|---|
addressWidth | Int | |
dataWidth | Int | |
idWidth | Int | |
userWidth | Int | |
useld | Boolean | true |
useRegion | Boolean | true |
useBurst | Boolean | true |
useLock | Boolean | true |
useCache | Boolean | true |
useSize | Boolean | true |
useQos | Boolean | true |
useLen | Boolean | true |
useLast | Boolean | true |
useResp | Boolean | true |
useProt | Boolean | true |
useStrb | Boolean | true |
useUser | Boolean | false |
简而言之, SpinalHDL库中定义AXI4总线的方式如下:
case class Axi4(config: Axi4Config) extends Bundle with IMasterSlave{
val aw = Stream(Axi4Aw(config))
val w = Stream(Axi4W(config))
val b = Stream(Axi4B(config))
val ar = Stream(Axi4Ar(config))
val r = Stream(Axi4R(config))
override def asMaster(): Unit = {
master(ar,aw,w)
slave(r,b)
}
}
简单的使用样例:
val axiConfig = Axi4Config(
addressWidth = 32,
dataWidth = 32,
idWidth = 4
)
val axiX = Axi4(axiConfig)
val axiY = Axi4(axiConfig)
when(axiY.aw.valid){
//...
}
变式
Axi4总线有三个变式:
| 类型 | 述 | | :———–: :————————————————————————————————————————————————————- ———————————————: | | Axi4ReadOnly | 只有AR和R通 在 | | Axi4WriteOnly | 只有AW、W和B通 在 | | Axi4Shared | 这种变式是该库的首创。
它使用4个通道, W, B,R, 还有一个名为AWR的新通道。
AWR通道可以用来传输AR和AW事务。要分离它们, 需要一个信号write
。
这种Axi4Shared变体的优点是使用更少的面积, 尤其是在互连方面。 |函数与操作
参数名 | 返回 | 描述 |
---|---|---|
X >> Y | 连接X到Y。能够像AXI4规范中指定的那样推断默认值, 并以安全的方式调整一些宽度。 | |
X << Y | 做与>>相反的操作 | |
X.toWriteOnly | Axi4WriteOnly | 返回一个由X驱动的Axi4WriteOnly总线 |
X.toReadOnly | Axi4ReadOnly | 返回一个由X驱动的Axi4ReadOnly总线 |
四、AvalonMM
简介
AvalonMM总线非常适合FPGA。它非常灵活:
与APB一样简单
在许多需要带宽的应用程序中, 比AHB表现更好, 因为AvalonMM有一种模式, 可以从命令中解耦读响应(减少延迟读延迟的影响)。
性能不如AXI, 但使用的面积少得多(读写命令使用相同的握手通道。主端口不需要存储挂起请求的地址以避免读/写风险)
配置和实例化
AvalonMM Bundle有一个构造参数
AvalonMMConfig
。由于Avalon总线的灵活性,AvalonMMConfig
可以作为许多配置元素。case class AvalonMMConfig( addressWidth : Int, dataWidth : Int, burstCountWidth : Int, useByteEnable : Boolean, useDebugAccess : Boolean, useRead : Boolean, useWrite : Boolean, useResponse : Boolean, useLock : Boolean, useWaitRequestn : Boolean, useReadDataValid : Boolean, useBurstCount : Boolean, //useEndOfPacket : Boolean, addressUnits : AddressUnits = symbols, burstCountUnits : AddressUnits = words, burstOnBurstBoundariesOnly : Boolean = false, constantBurstBehavior : Boolean = false, holdTime : Int = 0, linewrapBursts : Boolean = false, maximumPendingReadTransactions : Int = 1, maximumPendingWriteTransactions : Int = 0, // unlimited readLatency : Int = 0, readWaitTime : Int = 0, setupTime : Int = 0, writeWaitTime : Int = 0 )
这样的配置类也有一些函数:
| 函数名 | 返回 | 描述 | | :—————-: | :————: | :————————————–: | | getReadOnlyConfig | AvalonMMConfig | 返回一个类似的配置, 但禁用所有写入属性。 | | getWriteOnlyConfig | AvalonMMConfig | 返回一个类似的配置, 但禁用所有读属性 |
这个配置对象也有一些函数来提供一些AvalonMMConfig模板:
| 函数名 | 返回 | 描述 | | :———————————————: | :————: | :————————————–: | | fixed(addressWidth,dataWidth,readLatency) | AvalonMMConfig | 返回一个具有固定读取时间的简单配置。 | | pipelined(addressWidth,dataWidth) | AvalonMMConfig | 返回一个配置, 读取延迟可变 | | bursted(addressWidth,dataWidth,burstCountWidth) | AvalonMMConfig | 返回一个具有可变延迟读取和突发功能的配置 |
// 创建一个只写的AvalonMM配置, 具有突发能力和字节使能 val myAvalonConfig = AvalonMMConfig.bursted( addressWidth = addressWidth, dataWidth = memDataWidth, burstCountWidth = log2Up(burstSize + 1) ).copy( useByteEnable = true, constantBurstBehavior = true, burstOnBurstBoundariesOnly = true ).getWriteOnlyConfig // 创建一个利用该配置的总线实例 val bus = AvalonMM(myAvalonConfig)