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
whenMasked
1
2
3whenMasked(avec, amask: Bits) {
active(sth)
}whenIndexed
1
2
3whenIndexed(avec, aindex: UInt) {
active(sth)
}
带优先级的Mux
1 | object PriorityMux{ |
延迟的标志信号 DelayEvent
可以将一个标志信号延时多个cycle。(对这一flag直接 Delay
不是不行,只是在延迟的cycle数太大时过于浪费寄存器资源)存在两个控制延迟的方式,
def apply(event: Bool, cycle: BigInt): Bool
def 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
}
}