Spinal Utilities
Overview
SpinalHDL存在大量的零碎的feature,很不起眼但是非常有用。 core 模块和 lib 模块均包含有 util ,这里略微总结不在官方文档内的比较有用的功能。
隐式转换
从Scalal原生类型隐式转换到Spinal的硬件类型,并提供硬件描述相关功能。抑或是对一些原有类型的扩展。
Seq到Vec
import spinal.lib._
class TraversableOncePimped[T <: Data](pimped: Seq[T])
- 提供类似于Vec使用UInt访问内部数据的功能
- 提供
reduceBalanceTree - 提供
asBits - 提供简单的集合查找和计数功能:
def sExist(condition: T => Bool): Bool = (pimped map condition).fold(False)(_ || _)def sContains(value: T) : Bool = sExist(_ === value)def sFindFirst(condition: T => Bool) : (Bool,UInt)def sCount(condition: T => Bool): UInt = SetCount((pimped.map(condition)))def sCount(value: T): UInt = sCount(_ === value)
特殊的, Seq[Bool] 还提供 orR, andR, xorR 功能,将内部的Boolean全部与或非起来。
更基本的类 class TraversableOnceAnyPimped[T <: Any](pimped: Seq[T]) 支持 whenIndexed 功能,
1 | def apply(id : UInt)(gen : (T) => Unit): Unit ={ |
Tuple到Bits
import spinal.core._
class TuplePimperBase(product: Product)
提供类似于Verilog位拼接的功能,如:
1 | assign {cout, s} = {a, b, c}; |
字符串转Vec[Bits]
1 | val avec = "0123abcd".toVecOfByte |
Stream、Flow及Fragment自动转成其payload
需要 import DataCarrier._
不在需要引用 payload 来获得其payload。
时钟域的扩展
提供异步复位同步释放的扩展,可以从异步复位时钟域经由同步器获得新的同步释放时钟域
def withBufferedResetFrom(resetCd : ClockDomain, bufferDepth : Int = BufferCC.defaultDepth.get) : ClockDomain
对Seq的when
whenMasked1
2
3whenMasked(avec, amask: Bits) {
active(sth)
}whenIndexed1
2
3whenIndexed(avec, aindex: UInt) {
active(sth)
}
带优先级的Mux
1 | object PriorityMux{ |
延迟的标志信号 DelayEvent
可以将一个标志信号延时多个cycle。(对这一flag直接 Delay 不是不行,只是在延迟的cycle数太大时过于浪费寄存器资源)存在两个控制延迟的方式,
def apply(event: Bool, cycle: BigInt): Booldef apply(event: Bool, cycle: UInt): Bool
计数器扩展
可增减计数器,多请求计数器。
CounterUpDown提供decrement方法减一- 多请求:
1
2
3
4
5
6
7
8
9
10
11
12
13
14object CounterMultiRequest {
def apply(width: Int, requests : (Bool,(UInt) => UInt)*): UInt = {
val counter = Reg(UInt(width bit)) init(0)
var counterNext = cloneOf(counter)
counterNext := counter
for((cond,func) <- requests){
when(cond){
counterNext \= func(counterNext)
}
}
counter := counterNext
counter
}
}