本文作为SpinalHDL学习笔记第四十篇,介绍SpinalHDL中级示例。
目录:
1.分形计算器
2.串口
1.分形计算器
简介
此示例将展示使用数据流和定点计算实现一个未经优化的 Mandelbrot 分形计算器。
规范
组件将接收像素任务的一个 Stream(其中包含 Mandelbrot 空间中的 XY 坐标),并将生成一个像素结果的一个 Stream (包含对应任务的迭代次数)。
定义组件的 IO 为:
IO 名称 | 方向 | 类型 | 描述 |
cmd | slave | Stream[PixelTask] | 提供 XY 坐标来处理 |
rsp | master | Stream[PixelResult] | 返回对应 cmd 交换所需的迭代次数 |
让我们设计 PixelTask Bundle:
元素名称 | 类型 | 描述 |
x | SFix | Mandelbrot 空间中的坐标 |
y | SFix | Mandelbrot 空间中的坐标 |
定义 PixelResult Bundle :
元素名称 | 类型 | 描述 |
iteration | UInt | 求解 Mandelbrot 坐标所需的迭代次数 |
细化参数(泛型)
让我们定义为系统提供构造参数的类:
case class PixelSolverGenerics(fixAmplitude: Int,
fixResolution: Int,
iterationLimit: Int) {
val iterationWidth = log2Up(iterationLimit+1)
def iterationType = UInt(iterationWidth bits)
def fixType = SFix(
peak=fixAmplitude exp,
resolution=fixResolution exp
)
}
注解: iterationType 和 fxType 是可以调用来实例化新信号的函数,它就像 C 语言中的 typedef。
Bundle 定义
case class PixelTask(g: PixelSolverGenerics) extends Bundle {
val x, y = g.fixType
}
case class PixelResult(g: PixelSolverGenerics) extends Bundle {
val iteration = g.iterationType
}
组件实现
现在进行实现。下面是一个非常简单的实现,没有使用流水线处理/多线程技术。
ase class PixelSolver(g: PixelSolverGenerics) extends Component {
val io = new Bundle{
val cmd = slave Stream(PixelTask(g))
val rsp = master Stream(PixelResult(g))
}
import g._
//Define states
val x, y = Reg(fixType) init(0)
val iteration = Reg(iterationType) init(0)
//Do some shared calculation
val xx = x*x
val yy = y*y
val xy = x*y
//Apply default assignment
io.cmd.ready := False
io.rsp.valid := False
io.rsp.iteration := iteration
when(io.cmd.valid) {
//Is the mandelbrot iteration done ?
when(xx + yy >= 4.0 || iteration === iterationLimit) {
io.rsp.valid := True
when(io.rsp.ready){
io.cmd.ready := True
x := 0
y := 0
iteration := 0
}
} otherwise {
x := (xx - yy + io.cmd.x).truncated
y := (((xy) << 1) + io.cmd.y).truncated
iteration := iteration + 1
}
}
}