总线(bus)

一、AHB-Lite3

  1. 配置与实例化(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){
    //...
}
  1. 变式(Variations)

    有一个AhbLite3Master变体。唯一的区别是没有HREADYOUT信号。当互连线和从端口使用AhbLite3时, 这个变式应该只被master使用。

二、Apb3

  1. 简介

    AMBA3-APB总线通常用于连接低带宽外设。

  2. 配置和实例化

    首先, 每次创建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){
    //...
}
  1. 函数和运算(Functions and operators)

参数名 返回 描述
X >> Y 连接X到Y。Y的地址可以小于X
X << Y 做与>>相反的操作

三、Axi4

  1. 简介

    AXI4是ARM定义的高带宽总线

  2. 配置和实例化

    首先, 每次创建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){
    //...
}
  1. 变式

    Axi4总线有三个变式:

    | 类型 | 述 | | :———–: :————————————————————————————————————————————————————- ———————————————: | | Axi4ReadOnly | 只有AR和R通 在 | | Axi4WriteOnly | 只有AW、W和B通 在 | | Axi4Shared | 这种变式是该库的首创。
    它使用4个通道, W, B,R, 还有一个名为AWR的新通道。
    AWR通道可以用来传输AR和AW事务。要分离它们, 需要一个信号write
    这种Axi4Shared变体的优点是使用更少的面积, 尤其是在互连方面。 |

  2. 函数与操作

参数名 返回 描述
X >> Y 连接X到Y。能够像AXI4规范中指定的那样推断默认值, 并以安全的方式调整一些宽度。
X << Y 做与>>相反的操作
X.toWriteOnly Axi4WriteOnly 返回一个由X驱动的Axi4WriteOnly总线
X.toReadOnly Axi4ReadOnly 返回一个由X驱动的Axi4ReadOnly总线

四、AvalonMM

  1. 简介

    AvalonMM总线非常适合FPGA。它非常灵活:

    • 与APB一样简单

    • 在许多需要带宽的应用程序中, 比AHB表现更好, 因为AvalonMM有一种模式, 可以从命令中解耦读响应(减少延迟读延迟的影响)。

    • 性能不如AXI, 但使用的面积少得多(读写命令使用相同的握手通道。主端口不需要存储挂起请求的地址以避免读/写风险)

  2. 配置和实例化

    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)