You're reading an pre-release version of this documentation.
For the latest stable release version, please have a look at master.

正弦 ROM

让我们假设您想要生成一个正弦波,并且还有它的滤波版本(这在实际中完全没用,但让我们以此为例)。

参数名称

类型

描述

resolutionWidth

Int

用于表示数值的位宽

sampleCount

Int

一个正弦周期内的采样点数

IO名称

方向

类型

描述

sin

out

SInt(resolutionWidth bits)

作为正弦波的输出

sinFiltered

out

SInt(resolutionWidth bits)

作为滤波后正弦波的输出

那么让我们定义一个 Component

case class SineRom(resolutionWidth: Int, sampleCount: Int) extends Component {
  val io = new Bundle {
    val sin = out SInt(resolutionWidth bits)
    val sinFiltered = out SInt(resolutionWidth bits)
  }
...

为了在 sin 输出端口上输出正弦波,您可以定义一个 ROM,其包含正弦波一个周期内所有采样点(可能只是四分之一,但让我们以最简单的方式做事)。然后你可以用相位计数器读取该ROM,这将生成你的正弦波。

  // Calculate values for the lookup table
  def sinTable = for(sampleIndex <- 0 until sampleCount) yield {
    val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)
    S((sinValue * ((1<<resolutionWidth)/2-1)).toInt,resolutionWidth bits)
  }

  val rom =  Mem(SInt(resolutionWidth bits),initialContent = sinTable)
  val phase = Reg(UInt(log2Up(sampleCount) bits)) init 0
  phase := phase + 1

  io.sin := rom.readSync(phase)

随后生成 sinFiltered ,例如您可以使用一个一阶低通滤波器:

  io.sinFiltered := RegNext(io.sinFiltered  - (io.sinFiltered  >> 5) + (io.sin >> 5)) init 0

这是完整的代码:

case class SineRom(resolutionWidth: Int, sampleCount: Int) extends Component {
  val io = new Bundle {
    val sin = out SInt(resolutionWidth bits)
    val sinFiltered = out SInt(resolutionWidth bits)
  }

  // Calculate values for the lookup table
  def sinTable = for(sampleIndex <- 0 until sampleCount) yield {
    val sinValue = Math.sin(2 * Math.PI * sampleIndex / sampleCount)
    S((sinValue * ((1<<resolutionWidth)/2-1)).toInt,resolutionWidth bits)
  }

  val rom =  Mem(SInt(resolutionWidth bits),initialContent = sinTable)
  val phase = Reg(UInt(log2Up(sampleCount) bits)) init 0
  phase := phase + 1

  io.sin := rom.readSync(phase)

  io.sinFiltered := RegNext(io.sinFiltered  - (io.sinFiltered  >> 5) + (io.sin >> 5)) init 0
}