Chisel 提供了创建只读存储器和可读写存储器的机制
1、只读存储器 (ROM)
可以使用 Vec 类型来定义只读存储器,如示例:
Vec(inits: Seq[T])
Vec(elt0: T, elts: T*)
或者,可以通过一个被初始化的向量来创建一个只读存储器,形式为:
要么把一个元素为 Data 类型的序列作为参数,要么直接用若干个 Data 类型的元素作为参数。如:
用户可以创建一个小 ROM,初始化成1, 2, 4, 8,并且用一个计数器作为地址生成器来遍历它所有的值,如下例所示:
val m = Vec(Array(1.U, 2.U, 4.U, 8.U))
val r = m(counter(UInt(m.length.W)))
我们可以 ROM 创建一个有 n 个入口的 sine 函数的查找表,如下例所示:
def sinTable (amp: Double, n: Int) = {
val times =Range(0, n, 1).map(i => (i2Pi)/(n.toDouble-1) - Pi)
val inits =times.map(t => SInt(round(amp * sin(t)), width = 32))
Vec(inits)
}
def sinWave (amp: Double, n: Int) =sinTable(amp, n)(counter(UInt(n.W))
这里的 amp 用来缩放 ROM 中保存的定点数值。
2、可读写存储器 (Mem)
Chisel 支持两种类型的 RAM。
2.1 第一种 RAM 是同步(时序)写,异步(组合逻辑)读,用语法“Mem(数量, UInt(位宽))”来构建。如:
由于现代的 FPGA 和 ASIC 技术已经不再支持异步读 RAM,所以这种 RAM 会被综合成寄存器阵列。
2.2 第二种 RAM 则是同步(时序)读、写,用语法“SeqMem(数量, UInt(位宽))”来构建,这种 RAM 会被综合成实际的 SRAM。如:
单个读端口、单个写端口的 SRAM 可以如下设计:
val ram1r1w = Mem(1024, UInt(32.W))
val reg_raddr = Reg(UInt())
when (wen)
{
ram1r1w(waddr) := wdata
}
when (ren)
{
reg_raddr := raddr
}
val rdata = ram1r1w(reg_raddr)
如果读取和写入被放在在同一个 when 语句中,并且它们的条件是互斥的,那么就可以推断这是一个单端口 SRAM。
val ram1p = Mem(1024, UInt(32.W))
val reg_raddr = Reg(UInt())
when (wen)
{
ram1p(waddr) := wdata
}
.elsewhen (ren)
{
reg_raddr := raddr
}
val rdata = ram1p(reg_raddr)